From 0ee38e29ade5acc7fd9aa8955901c5fbc69c788f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 16 Sep 2011 15:22:28 +0200 Subject: [PATCH 001/161] [IMP] convert form widgets to use a root class to find themselves back in the rendered dom, instead of a root id bzr revid: xmo@openerp.com-20110916132228-h2qszo33q6z289qf --- addons/web/static/src/js/view_form.js | 22 ++++++++-------- addons/web/static/src/xml/base.xml | 37 +++++++++++++-------------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index e28936b850d..16a4ba908a7 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -82,7 +82,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# _.each(this.widgets, function(w) { w.start(); }); - this.$form_header = this.$element.find('#' + this.element_id + '_header'); + this.$form_header = this.$element.find('.oe_form_header'); this.$form_header.find('div.oe_form_pager button[data-pager-action]').click(function() { var action = $(this).data('pager-action'); self.on_pager_action(action); @@ -196,7 +196,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# } }, do_update_pager: function(hide_index) { - var $pager = this.$element.find('#' + this.element_id + '_header div.oe_form_pager'); + var $pager = this.$form_header.find('div.oe_form_pager'); var index = hide_index ? '-' : this.dataset.index + 1; $pager.find('span.oe_pager_index').html(index); $pager.find('span.oe_pager_count').html(this.dataset.ids.length); @@ -619,6 +619,7 @@ openerp.web.form.compute_domain = function(expr, fields) { openerp.web.form.Widget = openerp.web.Widget.extend(/** @lends openerp.web.form.Widget# */{ template: 'Widget', + identifier_prefix: 'formview-widget-', /** * @constructs openerp.web.form.Widget * @extends openerp.web.Widget @@ -632,11 +633,13 @@ openerp.web.form.Widget = openerp.web.Widget.extend(/** @lends openerp.web.form. this.modifiers = JSON.parse(this.node.attrs.modifiers || '{}'); this.type = this.type || node.tag; this.element_name = this.element_name || this.type; - this.element_id = [this.view.element_id, this.element_name, this.view.widgets_counter++].join("_"); + this.element_class = [ + 'formview', this.view.view_id, this.element_name, + this.view.widgets_counter++].join("_"); - this._super(view, this.element_id); + this._super(view); - this.view.widgets[this.element_id] = this; + this.view.widgets[this.element_class] = this; this.children = node.children; this.colspan = parseInt(node.attrs.colspan || 1, 10); this.decrease_max_width = 0; @@ -649,7 +652,7 @@ openerp.web.form.Widget = openerp.web.Widget.extend(/** @lends openerp.web.form. this.width = this.node.attrs.width; }, start: function() { - this.$element = $('#' + this.element_id); + this.$element = this.view.$element.find('.' + this.element_class); }, stop: function() { if (this.$element) { @@ -896,7 +899,7 @@ openerp.web.form.WidgetLabel = openerp.web.form.Widget.extend({ var self = this; this.$element.find("label").dblclick(function() { var widget = self['for'] || self; - console.log(widget.element_id , widget); + console.log(widget.element_class , widget); window.w = widget; }); } @@ -1932,9 +1935,8 @@ openerp.web.form.FieldOne2Many = openerp.web.form.Field.extend({ }, validate: function() { this.invalid = false; - var self = this; - var view = self.viewmanager.views[self.viewmanager.active_view].controller; - if (self.viewmanager.active_view === "form") { + var view = this.viewmanager.views[this.viewmanager.active_view].controller; + if (this.viewmanager.active_view === "form") { for (var f in view.fields) { f = view.fields[f]; if (!f.is_valid()) { diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml index c2b6ca0bdf2..daf85c43ee7 100644 --- a/addons/web/static/src/xml/base.xml +++ b/addons/web/static/src/xml/base.xml @@ -649,7 +649,7 @@ -
+
+
From 079f817e1cc21119560e291aaf8f4179acde3668 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 19 Sep 2011 17:22:10 +0200 Subject: [PATCH 011/161] [IMP] cleanup random stuff so events don't accumulate across switches, ending up breaking the form bzr revid: xmo@openerp.com-20110919152210-o828pz00vp7vuf5j --- addons/web/static/src/js/view_form.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index b3fd3d6dd6f..fdaff535fb8 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -94,6 +94,10 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# this.$form_header.find('button.oe_form_button_new').click(this.on_button_new); this.$form_header.find('button.oe_form_button_duplicate').click(this.on_button_duplicate); this.$form_header.find('button.oe_form_button_toggle').click(function () { + self.translatable_fields = []; + self.widgets = {}; + self.fields = {}; + self.$form_header.find('button').unbind('click'); self.registry = self.registry === openerp.web.form.widgets ? openerp.web.form.readonly : openerp.web.form.widgets; From 134437d3d1801223ad04ad870cd285401771ecdd Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 20 Sep 2011 13:21:47 +0200 Subject: [PATCH 012/161] [IMP] memoize template, add hacky form-repositioning method bzr revid: xmo@openerp.com-20110920112147-we4sqnc3we1v38lv --- addons/web/static/src/js/view_form.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index 82bfa817ef1..c9dcb65cba9 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -73,12 +73,19 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# w.stop(); }); }, + reposition: function ($e) { + this.$element = $e; + this.on_loaded(); + }, on_loaded: function(data) { var self = this; - this.fields_view = data; - var frame = new (this.registry.get_object('frame'))(this, this.fields_view.arch); + if (data) { + this.fields_view = data; + var frame = new (this.registry.get_object('frame'))(this, this.fields_view.arch); - this.$element.html(QWeb.render(this.form_template, { 'frame': frame, 'view': this })); + this.rendered = QWeb.render(this.form_template, { 'frame': frame, 'view': this }); + } + this.$element.html(this.rendered); _.each(this.widgets, function(w) { w.start(); }); From 0166aeabff370945f0e9c74cdd2128dccb27e7a1 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 20 Sep 2011 14:28:20 +0200 Subject: [PATCH 013/161] [ADD] bunch of tests bzr revid: xmo@openerp.com-20110920122820-5ql07msi0zjljhxn --- addons/web_tests/__init__.py | 1 + addons/web_tests/__openerp__.py | 8 ++++ addons/web_tests/static/src/css/web_tests.css | 3 ++ addons/web_tests/static/src/js/web_tests.js | 37 +++++++++++++++++++ 4 files changed, 49 insertions(+) create mode 100644 addons/web_tests/__init__.py create mode 100644 addons/web_tests/__openerp__.py create mode 100644 addons/web_tests/static/src/css/web_tests.css create mode 100644 addons/web_tests/static/src/js/web_tests.js diff --git a/addons/web_tests/__init__.py b/addons/web_tests/__init__.py new file mode 100644 index 00000000000..40a96afc6ff --- /dev/null +++ b/addons/web_tests/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/addons/web_tests/__openerp__.py b/addons/web_tests/__openerp__.py new file mode 100644 index 00000000000..d6221900f00 --- /dev/null +++ b/addons/web_tests/__openerp__.py @@ -0,0 +1,8 @@ +{ + "name": "Tests", + "version": "2.0", + "depends": [], + "js": ["static/src/js/*.js"], + "css": ['static/src/css/*.css'], + 'active': True, +} diff --git a/addons/web_tests/static/src/css/web_tests.css b/addons/web_tests/static/src/css/web_tests.css new file mode 100644 index 00000000000..b14d6541f43 --- /dev/null +++ b/addons/web_tests/static/src/css/web_tests.css @@ -0,0 +1,3 @@ +.oe-bunchaforms > div { + float: left; +} diff --git a/addons/web_tests/static/src/js/web_tests.js b/addons/web_tests/static/src/js/web_tests.js new file mode 100644 index 00000000000..b21275d1eb7 --- /dev/null +++ b/addons/web_tests/static/src/js/web_tests.js @@ -0,0 +1,37 @@ +openerp.web_tests = function (db) { + db.web.client_actions.add( + 'buncha-forms', 'instance.web_tests.BunchaForms'); + db.web_tests = {}; + db.web_tests.BunchaForms = db.web.Widget.extend({ + init: function (parent) { + this._super(parent); + this.dataset = new db.web.DataSetSearch(this, 'test.listview.relations'); + this.form = new db.web.FormView(this, this.dataset, false, { + action_buttons: false, + pager: false + }); + this.form.registry = db.web.form.readonly; + }, + render: function () { + return '
'; + }, + start: function () { + $.when( + this.dataset.read_slice(), + this.form.appendTo(this.$element)).then(this.on_everything_loaded); + }, + on_everything_loaded: function (slice) { + var records = slice[0].records; + if (!records.length) { + this.form.on_record_loaded({}); + return; + } + this.form.on_record_loaded(records[0]); + _(records.slice(1)).each(function (record, index) { + this.dataset.index = index+1; + this.form.reposition($('
').appendTo(this.$element)); + this.form.on_record_loaded(record); + }, this); + } + }); +}; From c94872fc0236259e4c5155ab63f5e878f65e4556 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Sun, 25 Sep 2011 20:04:07 +0200 Subject: [PATCH 014/161] [ADD] basic colors support to listview via py.parse bzr revid: xmo@openerp.com-20110925180407-n0asxrrjeb1oo5a4 --- addons/web/__openerp__.py | 1 + addons/web/static/lib/py.parse/lib/py.js | 490 +++++++++++++++++++++++ addons/web/static/src/js/view_list.js | 31 ++ addons/web/static/src/xml/base.xml | 3 +- 4 files changed, 524 insertions(+), 1 deletion(-) create mode 100644 addons/web/static/lib/py.parse/lib/py.js diff --git a/addons/web/__openerp__.py b/addons/web/__openerp__.py index 74633fa4969..37a5d435a75 100644 --- a/addons/web/__openerp__.py +++ b/addons/web/__openerp__.py @@ -24,6 +24,7 @@ "static/lib/underscore/underscore.js", "static/lib/underscore/underscore.string.js", "static/lib/labjs/LAB.src.js", + "static/lib/py.parse/lib/py.js", "static/src/js/boot.js", "static/src/js/core.js", "static/src/js/dates.js", diff --git a/addons/web/static/lib/py.parse/lib/py.js b/addons/web/static/lib/py.parse/lib/py.js new file mode 100644 index 00000000000..d5cf304bb58 --- /dev/null +++ b/addons/web/static/lib/py.parse/lib/py.js @@ -0,0 +1,490 @@ +var py = {}; +(function (exports) { + var NUMBER = /^\d$/, + NAME_FIRST = /^[a-zA-Z_]$/, + NAME = /^[a-zA-Z0-9_]$/; + + var create = function (o, props) { + function F() {}; + F.prototype = o; + var inst = new F; + for(var name in props) { + if(!props.hasOwnProperty(name)) { continue; } + inst[name] = props[name]; + } + return inst; + } + + var symbols = {}; + var comparators = {}; + var Base = { + nud: function () { throw new Error(this.id + " undefined as prefix"); }, + led: function (led) { throw new Error(this.id + " undefined as infix"); }, + toString: function () { + if (this.id === '(constant)' || this.id === '(number)' || this.id === '(name)' || this.id === '(string)') { + return [this.id.slice(0, this.id.length-1), ' ', this.value, ')'].join(''); + } else if (this.id === '(end)') { + return '(end)'; + } else if (this.id === '(comparator)' ) { + var out = ['(comparator', this.expressions[0]]; + for (var i=0;i s.lbp) { + s.lbp = bp; + } + return s; + } + return symbols[id] = create(Base, { + id: id, + lbp: bp + }); + } + function constant(id) { + symbol(id).nud = function () { + this.id = "(constant)"; + this.value = id; + return this; + }; + }; + function prefix(id, bp, nud) { + symbol(id).nud = nud || function () { + this.first = expression(bp); + return this + } + } + function infix(id, bp, led) { + symbol(id, bp).led = led || function (left) { + this.first = left; + this.second = expression(bp); + return this; + } + } + function infixr(id, bp) { + symbol(id, bp).led = function (left) { + this.first = left; + this.second = expression(bp - 1); + return this; + } + } + function comparator(id) { + comparators[id] = true; + var bp = 60; + infix(id, bp, function (left) { + this.id = '(comparator)'; + this.operators = [id]; + this.expressions = [left, expression(bp)]; + while (token.id in comparators) { + this.operators.push(token.id); + advance(); + this.expressions.push( + expression(bp)); + } + return this; + }); + } + + constant('None'); constant('False'); constant('True'); + + symbol('(number)').nud = function () { return this; }; + symbol('(name)').nud = function () { return this; }; + symbol('(string)').nud = function () { return this; }; + symbol('(end)'); + + symbol(':'); symbol(')'); symbol(']'); symbol('}'); symbol(','); + symbol('else'); + + symbol('lambda', 20).nud = function () { + this.first = []; + if (token.id !== ':') { + for(;;) { + if (token.id !== '(name)') { + throw new Error('Excepted an argument name'); + } + this.first.push(token); + advance(); + if (token.id !== ',') { + break; + } + advance(','); + } + } + advance(':'); + this.second = expression(); + return this; + }; + infix('if', 20, function (left) { + this.first = left; + this.second = expression(); + advance('else'); + this.third = expression(); + return this; + }); + + infixr('or', 30); infixr('and', 40); prefix('not', 50); + + comparator('in'); comparator('not in'); + comparator('is'); comparator('is not'); + comparator('<'); comparator('<='); + comparator('>'); comparator('>='); + comparator('<>'); comparator('!='); comparator('=='); + + infix('|', 70); infix('^', 80), infix('&', 90); + + infix('<<', 100); infix('>>', 100); + + infix('+', 110); infix('-', 110); + + infix('*', 120); infix('/', 120); + infix('//', 120), infix('%', 120); + + prefix('-', 130); prefix('+', 130); prefix('~', 130) + + infixr('**', 140); + + infix('.', 150, function (left) { + if (token.id !== '(name)') { + throw new Error('Expected attribute name, got ', token.id); + } + this.first = left; + this.second = token; + advance(); + return this; + }); + symbol('(', 150).nud = function () { + this.first = []; + var comma = false; + if (token.id !== ')') { + while (true) { + if (token.id === ')') { + break; + } + this.first.push(expression()) + if (token.id !== ',') { + break; + } + comma = true; + advance(','); + } + } + advance(')'); + if (!this.first.length || comma) { + return this; + } else { + return this.first[0]; + } + }; + symbol('(').led = function (left) { + this.first = left; + this.second = []; + if (token.id !== ")") { + for(;;) { + this.second.push(expression()); + if (token.id !== ',') { + break; + } + advance(','); + } + } + advance(")"); + return this; + + }; + infix('[', 150, function (left) { + this.first = left + this.second = expression() + advance("]") + return this; + }) + symbol('[').nud = function () { + this.first = []; + if (token.id !== ']') { + for (;;) { + if (token.id === ']') { + break; + } + this.first.push(expression()); + if (token.id !== ',') { + break; + } + advance(','); + } + } + advance(']'); + return this; + }; + + symbol('{').nud = function () { + this.first = []; + if (token.id !== '}') { + for(;;) { + if (token.id === '}') { + break; + } + var key = expression(); + advance(':'); + var value = expression(); + this.first.push([key, value]); + if (token.id !== ',') { + break; + } + advance(','); + } + } + advance('}'); + return this; + }; + + var longops = { + '*': ['*'], + '<': ['<', '=', '>'], + '>': ['=', '>'], + '!': ['='], + '=': ['='], + '/': ['/'] + } + function Tokenizer(str) { + this.states = ['initial']; + this.tokens = []; + } + Tokenizer.prototype = { + builder: function (empty) { + var key = this.states[0] + '_builder'; + if (empty) { + var value = this[key]; + delete this[key]; + return value; + } else { + return this[key] = this[key] || []; + } + }, + simple: function (type) { + this.tokens.push({type: type}); + }, + push: function (new_state) { + this.states.push(new_state); + }, + pop: function () { + this.states.pop(); + }, + + feed: function (str, index) { + var s = this.states; + return this[s[s.length - 1]](str, index); + }, + + initial: function (str, index) { + var character = str[index]; + + if (character in longops) { + var follow = longops[character]; + for(var i=0, len=follow.length; i> at index " + index + + ", character [[" + character + "]]" + + "; parsed so far: " + this.tokens); + }, + string: function (str, index) { + var character = str[index]; + if (character === '"' || character === "'") { + this.tokens.push(create(symbols['(string)'], { + value: this.builder(true).join('') + })); + this.pop(); + return index + 1; + } + this.builder().push(character); + return index + 1; + }, + number: function (str, index) { + var character = str[index]; + if (!NUMBER.test(character)) { + this.tokens.push(create(symbols['(number)'], { + value: parseFloat(this.builder(true).join('')) + })); + this.pop(); + return index; + } + this.builder().push(character); + return index + 1; + }, + name: function (str, index) { + var character = str[index]; + if (!NAME.test(character)) { + var name = this.builder(true).join(''); + var symbol = symbols[name]; + if (symbol) { + if (name === 'in' && this.tokens[this.tokens.length-1].id === 'not') { + symbol = symbols['not in']; + this.tokens.pop(); + } else if (name === 'not' && this.tokens[this.tokens.length-1].id === 'is') { + symbol = symbols['is not']; + this.tokens.pop(); + } + this.tokens.push(create(symbol)); + } else { + this.tokens.push(create(symbols['(name)'], { + value: name + })); + } + this.pop(); + return index; + } + this.builder().push(character); + return index + 1; + } + } + + exports.tokenize = function tokenize(str) { + var index = 0, + str = str + '\0', + tokenizer = new Tokenizer(str); + do { + index = tokenizer.feed(str, index); + } while (index !== str.length) + return tokenizer.tokens; + } + + var token, next; + function expression(rbp) { + rbp = rbp || 0; + var t = token; + token = next(); + var left = t.nud(); + while (rbp < token.lbp) { + t = token; + token = next(); + left = t.led(left); + } + return left; + } + function advance(id) { + if (id && token.id !== id) { + throw new Error( + 'Expected "' + id + '", got "' + token.id + '"'); + } + token = next(); + } + + exports.object = create({}, {}); + exports.tuple = create(exports.object, { + __contains__: function (value) { + for(var i=0, len=this.values.length; i': return a > b; + case '>=': return a >= b; + case 'in': return b.__contains__(a); + case 'not in': return !b.__contains__(a); + } + throw new Error('SyntaxError: unknown comparator [[' + operator + ']]'); + } + exports.evaluate = function (expr, context) { + switch (expr.id) { + case '(name)': + var val = context[expr.value]; + if (val === undefined) { + throw new Error("NameError: name '" + expr.value + "' is not defined"); + } + return val; + case '(string)': + case '(number)': + return expr.value; + case '(comparator)': + var result, left = exports.evaluate(expr.expressions[0], context); + for(var i=0; i + t-att-data-id="record.get('id')" + t-att-style="view.color_for(record)"> From 6d6f22015a58df1c44368a7691ee24125acf7a6d Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Tue, 27 Sep 2011 20:38:30 +0200 Subject: [PATCH 015/161] [IMP] ir_sequence: whitespace and other hair cut changes. bzr revid: vmt@openerp.com-20110927183830-9mkkphmpzquyqsjn --- openerp/addons/base/ir/ir_sequence.py | 55 +++++++++++++++------------ 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/openerp/addons/base/ir/ir_sequence.py b/openerp/addons/base/ir/ir_sequence.py index 4267e92d54d..0b805cc886f 100644 --- a/openerp/addons/base/ir/ir_sequence.py +++ b/openerp/addons/base/ir/ir_sequence.py @@ -20,49 +20,55 @@ ############################################################################## import time -from osv import fields,osv -import pooler -class ir_sequence_type(osv.osv): +import openerp + +class ir_sequence_type(openerp.osv.osv.osv): _name = 'ir.sequence.type' _order = 'name' _columns = { - 'name': fields.char('Name',size=64, required=True), - 'code': fields.char('Code',size=32, required=True), + 'name': openerp.osv.fields.char('Name', size=64, required=True), + 'code': openerp.osv.fields.char('Code', size=32, required=True), } -ir_sequence_type() def _code_get(self, cr, uid, context={}): cr.execute('select code, name from ir_sequence_type') return cr.fetchall() -class ir_sequence(osv.osv): +class ir_sequence(openerp.osv.osv.osv): + """ Sequence model. + + The sequence model allows to define and use so-called sequence objects. + Such objects are used to generate unique identifiers in a transaction-safe + way. + + """ _name = 'ir.sequence' _order = 'name' _columns = { - 'name': fields.char('Name',size=64, required=True), - 'code': fields.selection(_code_get, 'Code',size=64, required=True), - 'active': fields.boolean('Active'), - 'prefix': fields.char('Prefix',size=64, help="Prefix value of the record for the sequence"), - 'suffix': fields.char('Suffix',size=64, help="Suffix value of the record for the sequence"), - 'number_next': fields.integer('Next Number', required=True, help="Next number of this sequence"), - 'number_increment': fields.integer('Increment Number', required=True, help="The next number of the sequence will be incremented by this number"), - 'padding' : fields.integer('Number padding', required=True, help="OpenERP will automatically adds some '0' on the left of the 'Next Number' to get the required padding size."), - 'company_id': fields.many2one('res.company', 'Company'), + 'name': openerp.osv.fields.char('Name', size=64, required=True), + 'code': openerp.osv.fields.selection(_code_get, 'Code',size=64, required=True), + 'active': openerp.osv.fields.boolean('Active'), + 'prefix': openerp.osv.fields.char('Prefix', size=64, help="Prefix value of the record for the sequence"), + 'suffix': openerp.osv.fields.char('Suffix', size=64, help="Suffix value of the record for the sequence"), + 'number_next': openerp.osv.fields.integer('Next Number', required=True, help="Next number of this sequence"), + 'number_increment': openerp.osv.fields.integer('Increment Number', required=True, help="The next number of the sequence will be incremented by this number"), + 'padding' : openerp.osv.fields.integer('Number padding', required=True, help="OpenERP will automatically adds some '0' on the left of the 'Next Number' to get the required padding size."), + 'company_id': openerp.osv.fields.many2one('res.company', 'Company'), } _defaults = { - 'active': lambda *a: True, + 'active': True, 'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'ir.sequence', context=c), - 'number_increment': lambda *a: 1, - 'number_next': lambda *a: 1, - 'padding' : lambda *a : 0, + 'number_increment': 1, + 'number_next': 1, + 'padding' : 0, } def _process(self, s): return (s or '') % { - 'year':time.strftime('%Y'), + 'year': time.strftime('%Y'), 'month': time.strftime('%m'), - 'day':time.strftime('%d'), + 'day': time.strftime('%d'), 'y': time.strftime('%y'), 'doy': time.strftime('%j'), 'woy': time.strftime('%W'), @@ -93,9 +99,8 @@ class ir_sequence(osv.osv): return self._process(res['prefix']) + self._process(res['suffix']) return False - def get(self, cr, uid, code): - return self.get_id(cr, uid, code, test='code') -ir_sequence() + def get(self, cr, uid, code, context=None): + return self.get_id(cr, uid, code, 'code', context) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 0a8fe1e3b5696dc5bf7d46154cb7c0f3335691f5 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Tue, 27 Sep 2011 23:36:12 +0200 Subject: [PATCH 016/161] [IMP] ir_sequence: draining the swamp while being up to my neck in alligators. bzr revid: vmt@openerp.com-20110927213612-y8qzz2cma1cmfo69 --- openerp/addons/base/ir/ir_sequence.py | 94 +++++++++++++++++++-------- 1 file changed, 67 insertions(+), 27 deletions(-) diff --git a/openerp/addons/base/ir/ir_sequence.py b/openerp/addons/base/ir/ir_sequence.py index 0b805cc886f..90b3a5892b7 100644 --- a/openerp/addons/base/ir/ir_sequence.py +++ b/openerp/addons/base/ir/ir_sequence.py @@ -31,10 +31,17 @@ class ir_sequence_type(openerp.osv.osv.osv): 'code': openerp.osv.fields.char('Code', size=32, required=True), } + _sql_constraints = [ + ('code_unique', 'unique(code)', '`code` must be unique.'), + ] + def _code_get(self, cr, uid, context={}): cr.execute('select code, name from ir_sequence_type') return cr.fetchall() +IMPLEMENTATION_SELECTION = \ + [('standard', 'Standard'), ('no_gap', 'No gap')] + class ir_sequence(openerp.osv.osv.osv): """ Sequence model. @@ -47,7 +54,12 @@ class ir_sequence(openerp.osv.osv.osv): _order = 'name' _columns = { 'name': openerp.osv.fields.char('Name', size=64, required=True), - 'code': openerp.osv.fields.selection(_code_get, 'Code',size=64, required=True), + 'code': openerp.osv.fields.selection(_code_get, 'Code', size=64, required=True), # TODO should it be unique? + 'implementation': openerp.osv.fields.selection( # TODO update the view + IMPLEMENTATION_SELECTION, 'Implementation', required=True, + help="Two sequence object implementations are offered: Standard " + "and 'No gap'. The later is slower than the former but forbids any" + " gap in the sequence (while they are possible in the former)."), 'active': openerp.osv.fields.boolean('Active'), 'prefix': openerp.osv.fields.char('Prefix', size=64, help="Prefix value of the record for the sequence"), 'suffix': openerp.osv.fields.char('Suffix', size=64, help="Suffix value of the record for the sequence"), @@ -57,6 +69,7 @@ class ir_sequence(openerp.osv.osv.osv): 'company_id': openerp.osv.fields.many2one('res.company', 'Company'), } _defaults = { + 'implementation': 'standard', 'active': True, 'company_id': lambda s,cr,uid,c: s.pool.get('res.company')._company_default_get(cr, uid, 'ir.sequence', context=c), 'number_increment': 1, @@ -64,42 +77,69 @@ class ir_sequence(openerp.osv.osv.osv): 'padding' : 0, } - def _process(self, s): - return (s or '') % { - 'year': time.strftime('%Y'), - 'month': time.strftime('%m'), - 'day': time.strftime('%d'), - 'y': time.strftime('%y'), - 'doy': time.strftime('%j'), - 'woy': time.strftime('%W'), - 'weekday': time.strftime('%w'), - 'h24': time.strftime('%H'), - 'h12': time.strftime('%I'), - 'min': time.strftime('%M'), - 'sec': time.strftime('%S'), + def create(self, cr, uid, values, context=None): + values = self._add_missing_default_values(cr, uid, values, context) + go = super(ir_sequence, self).create \ + if values['implementation'] == 'standard' else self.create_nogap + return go(cr, uid, values, context) + + def _interpolate(self, s, d): + return s % d if s else '' + + def _interpolation_dict(self): + t = time.localtime() # Actually, the server is always in UTC. + return { + 'year': time.strftime('%Y', t), + 'month': time.strftime('%m', t), + 'day': time.strftime('%d', t), + 'y': time.strftime('%y', t), + 'doy': time.strftime('%j', t), + 'woy': time.strftime('%W', t), + 'weekday': time.strftime('%w', t), + 'h24': time.strftime('%H', t), + 'h12': time.strftime('%I', t), + 'min': time.strftime('%M', t), + 'sec': time.strftime('%S', t), } - def get_id(self, cr, uid, sequence_id, test='id', context=None): - assert test in ('code','id') + # TODO rename 'test' to 'code_or_id' in account/sequence. + def get_id(self, cr, uid, sequence_code_or_id, code_or_id='id', context=None): + """ Draw an interpolated string using the specified sequence. + + The sequence to use is specified by the ``sequence_code_or_id`` + argument, which can be a code or an id (as controlled by the + ``code_or_id`` argument. + """ + assert code_or_id in ('code', 'id') company_ids = self.pool.get('res.company').search(cr, uid, [], context=context) - cr.execute('''SELECT id, number_next, prefix, suffix, padding - FROM ir_sequence - WHERE %s=%%s - AND active=true - AND (company_id in %%s or company_id is NULL) - ORDER BY company_id, id - FOR UPDATE NOWAIT''' % test, - (sequence_id, tuple(company_ids))) + cr.execute(''' + SELECT id, number_next, prefix, suffix, padding + FROM ir_sequence + WHERE %s=%%s + AND active=true + AND (company_id in %%s or company_id is NULL) + ORDER BY company_id, id + LIMIT 1 + FOR UPDATE NOWAIT''' % code_or_id, + (sequence_code_or_id, tuple(company_ids))) res = cr.dictfetchone() if res: - cr.execute('UPDATE ir_sequence SET number_next=number_next+number_increment WHERE id=%s AND active=true', (res['id'],)) + d = self._interpolation_dict() + interpolated_prefix = self._interpolate(res['prefix'], d) + interpolated_suffix = self._interpolate(res['suffix'], d) + cr.execute('UPDATE ir_sequence SET number_next=number_next+number_increment WHERE id=%s', (res['id'],)) if res['number_next']: - return self._process(res['prefix']) + '%%0%sd' % res['padding'] % res['number_next'] + self._process(res['suffix']) + return interpolated_prefix + '%%0%sd' % res['padding'] % res['number_next'] + interpolated_suffix else: - return self._process(res['prefix']) + self._process(res['suffix']) + # TODO what is this case used for ? + return interpolated_prefix + interpolated_suffix return False def get(self, cr, uid, code, context=None): + """ Draw an interpolated string using the specified sequence. + + The sequence to use is specified by its code. + """ return self.get_id(cr, uid, code, 'code', context) From 5f4ebc7b1c72fe8eb5dcd947761d8d8f03cd8891 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Wed, 28 Sep 2011 11:13:09 +0200 Subject: [PATCH 017/161] [IMP] ir_sequence: add support for PostgreSQL sequence. This is partly inspired by openlabs' Sequence Postgres module. Untested yet. bzr revid: vmt@openerp.com-20110928091309-098red2biba5uq73 --- openerp/addons/base/ir/ir_sequence.py | 152 +++++++++++++++++++++----- 1 file changed, 126 insertions(+), 26 deletions(-) diff --git a/openerp/addons/base/ir/ir_sequence.py b/openerp/addons/base/ir/ir_sequence.py index 90b3a5892b7..3ff5009b567 100644 --- a/openerp/addons/base/ir/ir_sequence.py +++ b/openerp/addons/base/ir/ir_sequence.py @@ -79,10 +79,51 @@ class ir_sequence(openerp.osv.osv.osv): def create(self, cr, uid, values, context=None): values = self._add_missing_default_values(cr, uid, values, context) - go = super(ir_sequence, self).create \ - if values['implementation'] == 'standard' else self.create_nogap + go = super(ir_sequence, self).create_postgres \ + if values['implementation'] == 'standard' else self.create return go(cr, uid, values, context) + def create_postgres(self, cr, uid, values, context=None): + """ Create a fast, gaps-allowed PostgreSQL sequence. + + :param values: same argument than for ``create()`` but the keys + ``number_increment`` and ``number_next`` must be present. + ``_add_missing_default_values()`` can be used to this effect. + :return: id of the newly created record + """ + id = super(ir_sequence, self).create(cr, uid, values, context) + self._create_sequence(cr, + values['number_increment'], values['number_next']) + return id + + def unlink(self, cr, uid, ids, context=None): + super(ir_sequence, self).unlink(cr, uid, ids, context) + self._drop_sequence(cr, ids) + + def write(self, cr, uid, ids, values, context=None): + ids = ids if isinstance(ids, (list, tuple)) else [ids] + new_implementation = values.get('implementation') + rows = self.read(cr, uid, ids, ['id,' 'implementation', + 'number_increment', 'number_next'], context) + super(ir_sequence, self).write(cr, uid, ids, values, context) + + for row in rows: + # 4 cases: we test the previous impl. against the new one. + if row['implementation'] == 'standard': + i = values.get('number_increment', row['number_increment']) + n = values.get('number_next', row['number_next']) + if new_implementation in ('standard', None): + self._alter_sequence(cr, row['id'], i, n) + else: + self._drop_sequence(cr, row['id']) + else: + if new_implementation in ('no_gap', None): + pass + else: + self._create_sequence(cr, row['id'], i, n) + + return True + def _interpolate(self, s, d): return s % d if s else '' @@ -110,30 +151,34 @@ class ir_sequence(openerp.osv.osv.osv): argument, which can be a code or an id (as controlled by the ``code_or_id`` argument. """ - assert code_or_id in ('code', 'id') - company_ids = self.pool.get('res.company').search(cr, uid, [], context=context) - cr.execute(''' - SELECT id, number_next, prefix, suffix, padding - FROM ir_sequence - WHERE %s=%%s - AND active=true - AND (company_id in %%s or company_id is NULL) - ORDER BY company_id, id - LIMIT 1 - FOR UPDATE NOWAIT''' % code_or_id, - (sequence_code_or_id, tuple(company_ids))) - res = cr.dictfetchone() - if res: - d = self._interpolation_dict() - interpolated_prefix = self._interpolate(res['prefix'], d) - interpolated_suffix = self._interpolate(res['suffix'], d) - cr.execute('UPDATE ir_sequence SET number_next=number_next+number_increment WHERE id=%s', (res['id'],)) - if res['number_next']: - return interpolated_prefix + '%%0%sd' % res['padding'] % res['number_next'] + interpolated_suffix - else: - # TODO what is this case used for ? - return interpolated_prefix + interpolated_suffix - return False + # TODO there is no access rights check on the sequence itself. + res = self._select_by_code_or_id(cr, uid, sequence_code_or_id, + code_or_id, context) + + if not res: + return False + + if res['implementation'] == 'standard': + cr.execute(""" + SELECT nextval('ir_sequence_%03d') + """, (res['id'],)) + res['number_next'] = cr.fetchone() + else: + cr.execute(""" + UPDATE ir_sequence + SET number_next=number_next+number_increment + WHERE id=%s + """, (res['id'],)) + + d = self._interpolation_dict() + interpolated_prefix = self._interpolate(res['prefix'], d) + interpolated_suffix = self._interpolate(res['suffix'], d) + if res['number_next']: + return interpolated_prefix + '%%0%sd' % res['padding'] % \ + res['number_next'] + interpolated_suffix + else: + # TODO what is this case used for ? + return interpolated_prefix + interpolated_suffix def get(self, cr, uid, code, context=None): """ Draw an interpolated string using the specified sequence. @@ -142,5 +187,60 @@ class ir_sequence(openerp.osv.osv.osv): """ return self.get_id(cr, uid, code, 'code', context) + def _select_by_code_or_id(self, cr, uid, sequence_code_or_id, code_or_id, context=None): + """ Read a sequence object. + + There is no access rights check on the sequence itself. + """ + assert code_or_id in ('code', 'id') + res_company = self.pool.get('res.company') + company_ids = res_company.search(cr, uid, [], context=context) + cr.execute(""" + SELECT id, number_next, prefix, suffix, padding, implementation + FROM ir_sequence + WHERE %s=%%s + AND active=true + AND (company_id in %%s or company_id is NULL) + ORDER BY company_id, id + LIMIT 1 + FOR UPDATE NOWAIT + """ % code_or_id, (sequence_code_or_id, tuple(company_ids))) + return cr.dictfetchone() + + def _create_sequence(self, cr, number_increment, number_next): + """ Create a PostreSQL sequence. + + There is no access rights check. + """ + cr.execute(""" + CREATE SEQUENCE ir_sequence_%03d INCREMENT BY %s START WITH %s + """, (id, number_increment, number_next)) + + def _drop_sequence(self, cr, ids): + """ Drop the PostreSQL sequence if it exists. + + There is no access rights check. + """ + + ids = ids if isinstance(ids, (list, tuple)) else [ids] + assert all(isinstance(i, (int, long)) for i in ids), \ + "Only ids in (int, long) allowed." + names = ','.join('ir_sequence_%03d' % i for i in ids) + + # RESTRICT is the default; it prevents dropping the sequence if an + # object depends on it. + cr.execute(""" + DROP SEQUENCE IF EXISTS %s RESTRICT + """ % names) + + def _alter_sequence(self, cr, id, number_increment, number_next): + """ Alter a PostreSQL sequence. + + There is no access rights check. + """ + cr.execute(""" + ALTER SEQUENCE ir_sequence_%03d INCREMENT BY %s RESTART WITH %s + """, (id, number_increment, number_next)) + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From f2c5556b68f6879766dadf6522e35f4afc16696e Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Wed, 28 Sep 2011 12:30:09 +0200 Subject: [PATCH 018/161] [FIX] ir_sequence: forgot id argument in _create_sequence(). bzr revid: vmt@openerp.com-20110928103009-17rw1af5ebauu3f5 --- openerp/addons/base/ir/ir_sequence.py | 22 ++++++----- tests/common.py | 47 ++++++++++++++++++++++ tests/test_ir_sequence.py | 57 +++++++++++++++++++++++++++ tests/test_xmlrpc.py | 54 ++++++------------------- 4 files changed, 129 insertions(+), 51 deletions(-) create mode 100644 tests/common.py create mode 100644 tests/test_ir_sequence.py diff --git a/openerp/addons/base/ir/ir_sequence.py b/openerp/addons/base/ir/ir_sequence.py index 3ff5009b567..086d48ac44d 100644 --- a/openerp/addons/base/ir/ir_sequence.py +++ b/openerp/addons/base/ir/ir_sequence.py @@ -54,7 +54,7 @@ class ir_sequence(openerp.osv.osv.osv): _order = 'name' _columns = { 'name': openerp.osv.fields.char('Name', size=64, required=True), - 'code': openerp.osv.fields.selection(_code_get, 'Code', size=64, required=True), # TODO should it be unique? + 'code': openerp.osv.fields.selection(_code_get, 'Code', size=64, required=True), 'implementation': openerp.osv.fields.selection( # TODO update the view IMPLEMENTATION_SELECTION, 'Implementation', required=True, help="Two sequence object implementations are offered: Standard " @@ -79,8 +79,8 @@ class ir_sequence(openerp.osv.osv.osv): def create(self, cr, uid, values, context=None): values = self._add_missing_default_values(cr, uid, values, context) - go = super(ir_sequence, self).create_postgres \ - if values['implementation'] == 'standard' else self.create + go = super(ir_sequence, self).create \ + if values['implementation'] == 'no_gap' else self.create_postgres return go(cr, uid, values, context) def create_postgres(self, cr, uid, values, context=None): @@ -92,7 +92,7 @@ class ir_sequence(openerp.osv.osv.osv): :return: id of the newly created record """ id = super(ir_sequence, self).create(cr, uid, values, context) - self._create_sequence(cr, + self._create_sequence(cr, id, values['number_increment'], values['number_next']) return id @@ -161,7 +161,7 @@ class ir_sequence(openerp.osv.osv.osv): if res['implementation'] == 'standard': cr.execute(""" SELECT nextval('ir_sequence_%03d') - """, (res['id'],)) + """ % res['id']) res['number_next'] = cr.fetchone() else: cr.execute(""" @@ -207,14 +207,15 @@ class ir_sequence(openerp.osv.osv.osv): """ % code_or_id, (sequence_code_or_id, tuple(company_ids))) return cr.dictfetchone() - def _create_sequence(self, cr, number_increment, number_next): + def _create_sequence(self, cr, id, number_increment, number_next): """ Create a PostreSQL sequence. There is no access rights check. """ + assert isinstance(id, (int, long)) cr.execute(""" - CREATE SEQUENCE ir_sequence_%03d INCREMENT BY %s START WITH %s - """, (id, number_increment, number_next)) + CREATE SEQUENCE ir_sequence_%03d INCREMENT BY %%s START WITH %%s + """ % id, (number_increment, number_next)) def _drop_sequence(self, cr, ids): """ Drop the PostreSQL sequence if it exists. @@ -238,9 +239,10 @@ class ir_sequence(openerp.osv.osv.osv): There is no access rights check. """ + assert isinstance(id, (int, long)) cr.execute(""" - ALTER SEQUENCE ir_sequence_%03d INCREMENT BY %s RESTART WITH %s - """, (id, number_increment, number_next)) + ALTER SEQUENCE ir_sequence_%03d INCREMENT BY %%s RESTART WITH %%s + """ % id, (number_increment, number_next)) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/tests/common.py b/tests/common.py new file mode 100644 index 00000000000..eb34772d1af --- /dev/null +++ b/tests/common.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +import os +import time +import unittest2 +import xmlrpclib + +import openerp + +ADDONS_PATH = os.environ['OPENERP_ADDONS_PATH'] +PORT = int(os.environ['OPENERP_PORT']) +DB = os.environ['OPENERP_DATABASE'] + +HOST = '127.0.0.1' + +ADMIN_USER = 'admin' +ADMIN_USER_ID = 1 +ADMIN_PASSWORD = 'admin' + +common_proxy_60 = None +db_proxy_60 = None +object_proxy_60 = None + +def setUpModule(): + """ + Start the OpenERP server similary to the openerp-server script and + setup some xmlrpclib proxies. + """ + openerp.tools.config['addons_path'] = ADDONS_PATH + openerp.tools.config['xmlrpc_port'] = PORT + openerp.service.start_services() + + global common_proxy_60 + global db_proxy_60 + global object_proxy_60 + + # Use the old (pre 6.1) API. + url = 'http://%s:%d/xmlrpc/' % (HOST, PORT) + common_proxy_60 = xmlrpclib.ServerProxy(url + 'common') + db_proxy_60 = xmlrpclib.ServerProxy(url + 'db') + object_proxy_60 = xmlrpclib.ServerProxy(url + 'object') + + # Ugly way to ensure the server is listening. + time.sleep(2) + +def tearDownModule(): + """ Shutdown the OpenERP server similarly to a single ctrl-c. """ + openerp.service.stop_services() diff --git a/tests/test_ir_sequence.py b/tests/test_ir_sequence.py new file mode 100644 index 00000000000..ef7e6784daa --- /dev/null +++ b/tests/test_ir_sequence.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Run with one of these commands: +# > OPENERP_ADDONS_PATH='../../addons/trunk' OPENERP_PORT=8069 \ +# OPENERP_DATABASE=yy PYTHONPATH=. python tests/test_ir_sequence.py +# > OPENERP_ADDONS_PATH='../../addons/trunk' OPENERP_PORT=8069 \ +# OPENERP_DATABASE=yy nosetests tests/test_ir_sequence.py +# > OPENERP_ADDONS_PATH='../../../addons/trunk' OPENERP_PORT=8069 \ +# OPENERP_DATABASE=yy PYTHONPATH=../:. unit2 test_ir_sequence +import os +import time +import unittest2 +import xmlrpclib + +import openerp +import common + +DB = common.DB +ADMIN_USER_ID = common.ADMIN_USER_ID + +setUpModule = common.setUpModule +tearDownModule = common.tearDownModule + +def registry(model): + return openerp.modules.registry.RegistryManager.get(DB)[model] + +def cursor(): + return openerp.modules.registry.RegistryManager.get(DB).db.cursor() + +class test_ir_sequence(unittest2.TestCase): + + def test_ir_sequence_create(self): + """ Try to create a sequence object. """ + cr = cursor() + try: + d = dict(code='test_sequence_type', name='Test sequence type') + c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + assert c + d = dict(code='test_sequence_type', name='Test sequence') + c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + assert c + cr.commit() + finally: + cr.close() + + def test_ir_sequence_search(self): + """ Try a search. """ + cr = cursor() + try: + ids = registry('ir.sequence').search(cr, ADMIN_USER_ID, [], {}) + assert ids + cr.commit() + finally: + cr.close() + +if __name__ == '__main__': + unittest2.main() + diff --git a/tests/test_xmlrpc.py b/tests/test_xmlrpc.py index 30af863f12d..35ba07b940a 100644 --- a/tests/test_xmlrpc.py +++ b/tests/test_xmlrpc.py @@ -12,43 +12,15 @@ import unittest2 import xmlrpclib import openerp +import common -ADDONS_PATH = os.environ['OPENERP_ADDONS_PATH'] -PORT = int(os.environ['OPENERP_PORT']) -DB = os.environ['OPENERP_DATABASE'] +DB = common.DB +ADMIN_USER = common.ADMIN_USER +ADMIN_USER_ID = common.ADMIN_USER_ID +ADMIN_PASSWORD = common.ADMIN_PASSWORD -HOST = '127.0.0.1' - -ADMIN_USER = 'admin' -ADMIN_USER_ID = 1 -ADMIN_PASSWORD = 'admin' - -common_proxy_60 = None -db_proxy_60 = None -object_proxy_60 = None - -def setUpModule(): - """ - Start the OpenERP server similary to the openerp-server script and - setup some xmlrpclib proxies. - """ - openerp.tools.config['addons_path'] = ADDONS_PATH - openerp.tools.config['xmlrpc_port'] = PORT - openerp.service.start_services() - - global common_proxy_60 - global db_proxy_60 - global object_proxy_60 - - # Use the old (pre 6.1) API. - url = 'http://%s:%d/xmlrpc/' % (HOST, PORT) - common_proxy_60 = xmlrpclib.ServerProxy(url + 'common') - db_proxy_60 = xmlrpclib.ServerProxy(url + 'db') - object_proxy_60 = xmlrpclib.ServerProxy(url + 'object') - -def tearDownModule(): - """ Shutdown the OpenERP server similarly to a single ctrl-c. """ - openerp.service.stop_services() +setUpModule = common.setUpModule +tearDownModule = common.tearDownModule class test_xmlrpc(unittest2.TestCase): @@ -57,26 +29,26 @@ class test_xmlrpc(unittest2.TestCase): Simulate a OpenERP client requesting the creation of a database and polling the server until the creation is complete. """ - progress_id = db_proxy_60.create(ADMIN_PASSWORD, DB, True, False, - ADMIN_PASSWORD) + progress_id = common.db_proxy_60.create(ADMIN_PASSWORD, DB, True, + False, ADMIN_PASSWORD) while True: time.sleep(1) - progress, users = db_proxy_60.get_progress(ADMIN_PASSWORD, + progress, users = common.db_proxy_60.get_progress(ADMIN_PASSWORD, progress_id) if progress == 1.0: break def test_xmlrpc_login(self): """ Try to login on the common service. """ - uid = common_proxy_60.login(DB, ADMIN_USER, ADMIN_PASSWORD) + uid = common.common_proxy_60.login(DB, ADMIN_USER, ADMIN_PASSWORD) assert uid == ADMIN_USER_ID def test_xmlrpc_ir_model_search(self): """ Try a search on the object service. """ - ids = object_proxy_60.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, + ids = common.object_proxy_60.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, 'ir.model', 'search', []) assert ids - ids = object_proxy_60.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, + ids = common.object_proxy_60.execute(DB, ADMIN_USER_ID, ADMIN_PASSWORD, 'ir.model', 'search', [], {}) assert ids From eeaa2a7f8073153e5bb838ff5ace51215d18d68a Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Wed, 28 Sep 2011 13:42:29 +0200 Subject: [PATCH 019/161] [FIX] ir_sequence: do the FOR UPDATE NO WAIT only in the No-gap sequence. bzr revid: vmt@openerp.com-20110928114229-1g6r5et5frj26wam --- openerp/addons/base/ir/ir_sequence.py | 14 +++-- tests/test_ir_sequence.py | 74 ++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/openerp/addons/base/ir/ir_sequence.py b/openerp/addons/base/ir/ir_sequence.py index 086d48ac44d..c4d1a6f988b 100644 --- a/openerp/addons/base/ir/ir_sequence.py +++ b/openerp/addons/base/ir/ir_sequence.py @@ -153,7 +153,7 @@ class ir_sequence(openerp.osv.osv.osv): """ # TODO there is no access rights check on the sequence itself. res = self._select_by_code_or_id(cr, uid, sequence_code_or_id, - code_or_id, context) + code_or_id, False, context) if not res: return False @@ -164,6 +164,9 @@ class ir_sequence(openerp.osv.osv.osv): """ % res['id']) res['number_next'] = cr.fetchone() else: + # Read again with FOR UPDATE NO WAIT. + res = self._select_by_code_or_id(cr, uid, sequence_code_or_id, + code_or_id, True, context) cr.execute(""" UPDATE ir_sequence SET number_next=number_next+number_increment @@ -187,7 +190,8 @@ class ir_sequence(openerp.osv.osv.osv): """ return self.get_id(cr, uid, code, 'code', context) - def _select_by_code_or_id(self, cr, uid, sequence_code_or_id, code_or_id, context=None): + def _select_by_code_or_id(self, cr, uid, sequence_code_or_id, code_or_id, + for_update_no_wait, context=None): """ Read a sequence object. There is no access rights check on the sequence itself. @@ -195,6 +199,7 @@ class ir_sequence(openerp.osv.osv.osv): assert code_or_id in ('code', 'id') res_company = self.pool.get('res.company') company_ids = res_company.search(cr, uid, [], context=context) + funw = 'FOR UPDATE NOWAIT' if for_update_no_wait else '' cr.execute(""" SELECT id, number_next, prefix, suffix, padding, implementation FROM ir_sequence @@ -203,8 +208,9 @@ class ir_sequence(openerp.osv.osv.osv): AND (company_id in %%s or company_id is NULL) ORDER BY company_id, id LIMIT 1 - FOR UPDATE NOWAIT - """ % code_or_id, (sequence_code_or_id, tuple(company_ids))) + %s + """ % (code_or_id, funw), + (sequence_code_or_id, tuple(company_ids))) return cr.dictfetchone() def _create_sequence(self, cr, id, number_increment, number_next): diff --git a/tests/test_ir_sequence.py b/tests/test_ir_sequence.py index ef7e6784daa..0fc7aec5b50 100644 --- a/tests/test_ir_sequence.py +++ b/tests/test_ir_sequence.py @@ -7,6 +7,7 @@ # > OPENERP_ADDONS_PATH='../../../addons/trunk' OPENERP_PORT=8069 \ # OPENERP_DATABASE=yy PYTHONPATH=../:. unit2 test_ir_sequence import os +import psycopg2 import time import unittest2 import xmlrpclib @@ -26,7 +27,8 @@ def registry(model): def cursor(): return openerp.modules.registry.RegistryManager.get(DB).db.cursor() -class test_ir_sequence(unittest2.TestCase): +class test_ir_sequence_standard(unittest2.TestCase): + """ A few tests for a 'Standard' (i.e. PostgreSQL) sequence. """ def test_ir_sequence_create(self): """ Try to create a sequence object. """ @@ -52,6 +54,76 @@ class test_ir_sequence(unittest2.TestCase): finally: cr.close() + def test_ir_sequence_draw(self): + """ Try to draw a number. """ + cr = cursor() + try: + n = registry('ir.sequence').get(cr, ADMIN_USER_ID, 'test_sequence_type', {}) + assert n + cr.commit() + finally: + cr.close() + + def test_ir_sequence_draw_twice(self): + """ Try to draw a number from two transactions. """ + cr0 = cursor() + cr1 = cursor() + try: + n0 = registry('ir.sequence').get(cr0, ADMIN_USER_ID, 'test_sequence_type', {}) + assert n0 + n1 = registry('ir.sequence').get(cr1, ADMIN_USER_ID, 'test_sequence_type', {}) + assert n1 + cr0.commit() + cr1.commit() + finally: + cr0.close() + cr1.close() + +class test_ir_sequence_no_gap(unittest2.TestCase): + """ Copy of the previous tests for a 'No gap' sequence. """ + + def test_ir_sequence_create_no_gap(self): + """ Try to create a sequence object. """ + cr = cursor() + try: + d = dict(code='test_sequence_type_2', name='Test sequence type') + c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + assert c + d = dict(code='test_sequence_type_2', name='Test sequence', + implementation='no_gap') + c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + assert c + cr.commit() + finally: + cr.close() + + def test_ir_sequence_draw_no_gap(self): + """ Try to draw a number. """ + cr = cursor() + try: + n = registry('ir.sequence').get(cr, ADMIN_USER_ID, 'test_sequence_type_2', {}) + assert n + cr.commit() + finally: + cr.close() + + def test_ir_sequence_draw_twice_no_gap(self): + """ Try to draw a number from two transactions. + This is expected to not work. + """ + cr0 = cursor() + cr1 = cursor() + try: + msg_re = '^could not obtain lock on row in relation "ir_sequence"$' + with self.assertRaisesRegexp(psycopg2.OperationalError, msg_re): + n0 = registry('ir.sequence').get(cr0, ADMIN_USER_ID, 'test_sequence_type_2', {}) + assert n0 + n1 = registry('ir.sequence').get(cr1, ADMIN_USER_ID, 'test_sequence_type_2', {}) + finally: + cr0.close() + cr1.close() + + if __name__ == '__main__': unittest2.main() From 7ac3c9077435a1e7c25328891600e4b203dc4731 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Wed, 28 Sep 2011 15:05:48 +0200 Subject: [PATCH 020/161] [FIX] ir_sequence: check access right on get_id(), unlink returns True. bzr revid: vmt@openerp.com-20110928130548-ldg97pjo5zex0qab --- openerp/addons/base/ir/ir_sequence.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openerp/addons/base/ir/ir_sequence.py b/openerp/addons/base/ir/ir_sequence.py index c4d1a6f988b..4d10eefe75e 100644 --- a/openerp/addons/base/ir/ir_sequence.py +++ b/openerp/addons/base/ir/ir_sequence.py @@ -99,6 +99,7 @@ class ir_sequence(openerp.osv.osv.osv): def unlink(self, cr, uid, ids, context=None): super(ir_sequence, self).unlink(cr, uid, ids, context) self._drop_sequence(cr, ids) + return True def write(self, cr, uid, ids, values, context=None): ids = ids if isinstance(ids, (list, tuple)) else [ids] @@ -151,7 +152,7 @@ class ir_sequence(openerp.osv.osv.osv): argument, which can be a code or an id (as controlled by the ``code_or_id`` argument. """ - # TODO there is no access rights check on the sequence itself. + self.check_read(cr, uid) res = self._select_by_code_or_id(cr, uid, sequence_code_or_id, code_or_id, False, context) From 42fe3d4ff5594afa16f34e926fb0a8ee40dc771c Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Wed, 28 Sep 2011 15:27:44 +0200 Subject: [PATCH 021/161] [IMP] ir_sequence: added the new "implementation" field in the views. bzr revid: vmt@openerp.com-20110928132744-lb8m15yzg7kc3e56 --- openerp/addons/base/ir/ir.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openerp/addons/base/ir/ir.xml b/openerp/addons/base/ir/ir.xml index 2792259773d..79490542b1c 100644 --- a/openerp/addons/base/ir/ir.xml +++ b/openerp/addons/base/ir/ir.xml @@ -176,6 +176,7 @@ + @@ -215,6 +216,7 @@ + From 6929d9f3c85d7623c86487e030c8464bb0d6c530 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Wed, 28 Sep 2011 15:31:01 +0200 Subject: [PATCH 022/161] [FIX] ir_sequence: any merge proposal should touch as many .po files as possible. bzr revid: vmt@openerp.com-20110928133101-z1baqrqw7yb2u73c --- openerp/addons/base/i18n/af.po | 2 +- openerp/addons/base/i18n/am.po | 2 +- openerp/addons/base/i18n/ar.po | 2 +- openerp/addons/base/i18n/base.pot | 2 +- openerp/addons/base/i18n/bg.po | 2 +- openerp/addons/base/i18n/bs.po | 2 +- openerp/addons/base/i18n/ca.po | 2 +- openerp/addons/base/i18n/cs.po | 2 +- openerp/addons/base/i18n/da.po | 2 +- openerp/addons/base/i18n/de.po | 2 +- openerp/addons/base/i18n/el.po | 2 +- openerp/addons/base/i18n/en_GB.po | 4 ++-- openerp/addons/base/i18n/es.po | 2 +- openerp/addons/base/i18n/es_AR.po | 2 +- openerp/addons/base/i18n/es_CL.po | 2 +- openerp/addons/base/i18n/es_EC.po | 2 +- openerp/addons/base/i18n/et.po | 2 +- openerp/addons/base/i18n/eu.po | 2 +- openerp/addons/base/i18n/fa.po | 2 +- openerp/addons/base/i18n/fa_AF.po | 2 +- openerp/addons/base/i18n/fi.po | 2 +- openerp/addons/base/i18n/fr.po | 2 +- openerp/addons/base/i18n/gl.po | 2 +- openerp/addons/base/i18n/he.po | 2 +- openerp/addons/base/i18n/hr.po | 2 +- openerp/addons/base/i18n/hu.po | 4 ++-- openerp/addons/base/i18n/hy.po | 2 +- openerp/addons/base/i18n/id.po | 2 +- openerp/addons/base/i18n/is.po | 2 +- openerp/addons/base/i18n/it.po | 2 +- openerp/addons/base/i18n/ja.po | 2 +- openerp/addons/base/i18n/kk.po | 2 +- openerp/addons/base/i18n/ko.po | 2 +- openerp/addons/base/i18n/lt.po | 2 +- openerp/addons/base/i18n/lt_LT.po | 2 +- openerp/addons/base/i18n/lv.po | 2 +- openerp/addons/base/i18n/mk.po | 2 +- openerp/addons/base/i18n/mn.po | 2 +- openerp/addons/base/i18n/nb.po | 2 +- openerp/addons/base/i18n/nl.po | 2 +- openerp/addons/base/i18n/nl_BE.po | 2 +- openerp/addons/base/i18n/nl_NL.po | 2 +- openerp/addons/base/i18n/pl.po | 2 +- openerp/addons/base/i18n/pt.po | 2 +- openerp/addons/base/i18n/pt_BR.po | 2 +- openerp/addons/base/i18n/ro.po | 2 +- openerp/addons/base/i18n/ru.po | 2 +- openerp/addons/base/i18n/sk.po | 2 +- openerp/addons/base/i18n/sl.po | 2 +- openerp/addons/base/i18n/sq.po | 2 +- openerp/addons/base/i18n/sr.po | 2 +- openerp/addons/base/i18n/sr@latin.po | 2 +- openerp/addons/base/i18n/sv.po | 2 +- openerp/addons/base/i18n/th.po | 2 +- openerp/addons/base/i18n/tlh.po | 2 +- openerp/addons/base/i18n/tr.po | 2 +- openerp/addons/base/i18n/uk.po | 2 +- openerp/addons/base/i18n/uk_UA.po | 2 +- openerp/addons/base/i18n/ur.po | 2 +- openerp/addons/base/i18n/vi.po | 2 +- openerp/addons/base/i18n/zh_CN.po | 2 +- openerp/addons/base/i18n/zh_HK.po | 2 +- openerp/addons/base/i18n/zh_TW.po | 2 +- openerp/addons/base/ir/ir_sequence.py | 2 +- 64 files changed, 66 insertions(+), 66 deletions(-) diff --git a/openerp/addons/base/i18n/af.po b/openerp/addons/base/i18n/af.po index 72547d34bc1..87150c74641 100644 --- a/openerp/addons/base/i18n/af.po +++ b/openerp/addons/base/i18n/af.po @@ -5431,7 +5431,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/am.po b/openerp/addons/base/i18n/am.po index 7fa923c0660..31d0553c768 100644 --- a/openerp/addons/base/i18n/am.po +++ b/openerp/addons/base/i18n/am.po @@ -5431,7 +5431,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/ar.po b/openerp/addons/base/i18n/ar.po index b50c02ca98d..afe9a26e63a 100644 --- a/openerp/addons/base/i18n/ar.po +++ b/openerp/addons/base/i18n/ar.po @@ -5430,7 +5430,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/base.pot b/openerp/addons/base/i18n/base.pot index 9484a376151..55c648f89af 100644 --- a/openerp/addons/base/i18n/base.pot +++ b/openerp/addons/base/i18n/base.pot @@ -5217,7 +5217,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/bg.po b/openerp/addons/base/i18n/bg.po index 02da984c8b3..bb9f54a129d 100644 --- a/openerp/addons/base/i18n/bg.po +++ b/openerp/addons/base/i18n/bg.po @@ -5572,7 +5572,7 @@ msgstr "Преводи" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Брой на остъпката" #. module: base diff --git a/openerp/addons/base/i18n/bs.po b/openerp/addons/base/i18n/bs.po index 80691631cf8..1cd99f744ad 100644 --- a/openerp/addons/base/i18n/bs.po +++ b/openerp/addons/base/i18n/bs.po @@ -5439,7 +5439,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/ca.po b/openerp/addons/base/i18n/ca.po index 58c927285eb..6e9d7d6a6e7 100644 --- a/openerp/addons/base/i18n/ca.po +++ b/openerp/addons/base/i18n/ca.po @@ -5709,7 +5709,7 @@ msgstr "Traduccions" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Omplenat del número" #. module: base diff --git a/openerp/addons/base/i18n/cs.po b/openerp/addons/base/i18n/cs.po index 1a20a156fe9..e356d0b0973 100644 --- a/openerp/addons/base/i18n/cs.po +++ b/openerp/addons/base/i18n/cs.po @@ -5529,7 +5529,7 @@ msgstr "Překlady" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Zarovnání čísla" #. module: base diff --git a/openerp/addons/base/i18n/da.po b/openerp/addons/base/i18n/da.po index 2fa355ab21a..2968a29195b 100644 --- a/openerp/addons/base/i18n/da.po +++ b/openerp/addons/base/i18n/da.po @@ -5431,7 +5431,7 @@ msgstr "Oversættelser" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/de.po b/openerp/addons/base/i18n/de.po index 4dbe8f4c0cf..c2fe1af3b93 100644 --- a/openerp/addons/base/i18n/de.po +++ b/openerp/addons/base/i18n/de.po @@ -5702,7 +5702,7 @@ msgstr "Übersetzungen" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Stellenanzahl" #. module: base diff --git a/openerp/addons/base/i18n/el.po b/openerp/addons/base/i18n/el.po index 4bca6580496..9e5cc4245c9 100644 --- a/openerp/addons/base/i18n/el.po +++ b/openerp/addons/base/i18n/el.po @@ -5614,7 +5614,7 @@ msgstr "Μεταφράσεις" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Συμπλήρωση αριθμών" #. module: base diff --git a/openerp/addons/base/i18n/en_GB.po b/openerp/addons/base/i18n/en_GB.po index 45a31676521..d013bbc9be6 100644 --- a/openerp/addons/base/i18n/en_GB.po +++ b/openerp/addons/base/i18n/en_GB.po @@ -5669,8 +5669,8 @@ msgstr "Translations" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" -msgstr "Number padding" +msgid "Number Padding" +msgstr "Number Padding" #. module: base #: view:ir.actions.report.xml:0 diff --git a/openerp/addons/base/i18n/es.po b/openerp/addons/base/i18n/es.po index 75c938bb99f..b21773bb137 100644 --- a/openerp/addons/base/i18n/es.po +++ b/openerp/addons/base/i18n/es.po @@ -5723,7 +5723,7 @@ msgstr "Traducciones" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Relleno del número" #. module: base diff --git a/openerp/addons/base/i18n/es_AR.po b/openerp/addons/base/i18n/es_AR.po index f22db5e97a5..3eac408dd86 100644 --- a/openerp/addons/base/i18n/es_AR.po +++ b/openerp/addons/base/i18n/es_AR.po @@ -4778,7 +4778,7 @@ msgstr "Traducciones" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Relleno del número" #. module: base diff --git a/openerp/addons/base/i18n/es_CL.po b/openerp/addons/base/i18n/es_CL.po index 6a7b66979ae..6e1328dd1d4 100644 --- a/openerp/addons/base/i18n/es_CL.po +++ b/openerp/addons/base/i18n/es_CL.po @@ -5725,7 +5725,7 @@ msgstr "Traducciones" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Relleno del número" #. module: base diff --git a/openerp/addons/base/i18n/es_EC.po b/openerp/addons/base/i18n/es_EC.po index 172217838e6..62371e70beb 100644 --- a/openerp/addons/base/i18n/es_EC.po +++ b/openerp/addons/base/i18n/es_EC.po @@ -5712,7 +5712,7 @@ msgstr "Traducciones" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Relleno del número" #. module: base diff --git a/openerp/addons/base/i18n/et.po b/openerp/addons/base/i18n/et.po index 6062726cdc9..f5efbb2f667 100644 --- a/openerp/addons/base/i18n/et.po +++ b/openerp/addons/base/i18n/et.po @@ -5488,7 +5488,7 @@ msgstr "Tõlked" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Arvu täidistus" #. module: base diff --git a/openerp/addons/base/i18n/eu.po b/openerp/addons/base/i18n/eu.po index 8b92327e5ac..0c1ac0ac100 100644 --- a/openerp/addons/base/i18n/eu.po +++ b/openerp/addons/base/i18n/eu.po @@ -5431,7 +5431,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/fa.po b/openerp/addons/base/i18n/fa.po index 584d51a545e..517a9b87e19 100644 --- a/openerp/addons/base/i18n/fa.po +++ b/openerp/addons/base/i18n/fa.po @@ -5496,7 +5496,7 @@ msgstr "برگردان‌ها" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "پیمایش شمارگانی" #. module: base diff --git a/openerp/addons/base/i18n/fa_AF.po b/openerp/addons/base/i18n/fa_AF.po index d730070ecf9..1e0010a8fb4 100644 --- a/openerp/addons/base/i18n/fa_AF.po +++ b/openerp/addons/base/i18n/fa_AF.po @@ -5431,7 +5431,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/fi.po b/openerp/addons/base/i18n/fi.po index 16526bf9807..c47ec894821 100644 --- a/openerp/addons/base/i18n/fi.po +++ b/openerp/addons/base/i18n/fi.po @@ -5664,7 +5664,7 @@ msgstr "Käännökset" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Täytenumerot" #. module: base diff --git a/openerp/addons/base/i18n/fr.po b/openerp/addons/base/i18n/fr.po index 6fb9188fd3c..6ce408bc01a 100644 --- a/openerp/addons/base/i18n/fr.po +++ b/openerp/addons/base/i18n/fr.po @@ -5717,7 +5717,7 @@ msgstr "Traductions" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Remplissage" #. module: base diff --git a/openerp/addons/base/i18n/gl.po b/openerp/addons/base/i18n/gl.po index 8547223c29c..b2e33836902 100644 --- a/openerp/addons/base/i18n/gl.po +++ b/openerp/addons/base/i18n/gl.po @@ -5695,7 +5695,7 @@ msgstr "Traducións" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Número de enchido" #. module: base diff --git a/openerp/addons/base/i18n/he.po b/openerp/addons/base/i18n/he.po index 0e14797c6ee..07fda35ca86 100644 --- a/openerp/addons/base/i18n/he.po +++ b/openerp/addons/base/i18n/he.po @@ -5472,7 +5472,7 @@ msgstr "תרגומים" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/hr.po b/openerp/addons/base/i18n/hr.po index e82d8fb80cc..f7186b309ac 100644 --- a/openerp/addons/base/i18n/hr.po +++ b/openerp/addons/base/i18n/hr.po @@ -5553,7 +5553,7 @@ msgstr "Prijevodi" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Dopunjavanje na duljinu" #. module: base diff --git a/openerp/addons/base/i18n/hu.po b/openerp/addons/base/i18n/hu.po index 043b188ece7..35e0b0fb423 100644 --- a/openerp/addons/base/i18n/hu.po +++ b/openerp/addons/base/i18n/hu.po @@ -5666,8 +5666,8 @@ msgstr "Fordítások" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" -msgstr "Number padding" +msgid "Number Padding" +msgstr "Number Padding" #. module: base #: view:ir.actions.report.xml:0 diff --git a/openerp/addons/base/i18n/hy.po b/openerp/addons/base/i18n/hy.po index f47eb825bc2..2ab57b9b7fa 100644 --- a/openerp/addons/base/i18n/hy.po +++ b/openerp/addons/base/i18n/hy.po @@ -5431,7 +5431,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/id.po b/openerp/addons/base/i18n/id.po index 969f42eb804..dc1d81aa8bb 100644 --- a/openerp/addons/base/i18n/id.po +++ b/openerp/addons/base/i18n/id.po @@ -5435,7 +5435,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/is.po b/openerp/addons/base/i18n/is.po index f0973c0a8e4..6f29f97bb15 100644 --- a/openerp/addons/base/i18n/is.po +++ b/openerp/addons/base/i18n/is.po @@ -5431,7 +5431,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/it.po b/openerp/addons/base/i18n/it.po index 3a106c0498a..bbd01e7eaaf 100644 --- a/openerp/addons/base/i18n/it.po +++ b/openerp/addons/base/i18n/it.po @@ -5713,7 +5713,7 @@ msgstr "Traduzioni" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Riempimento Numero" #. module: base diff --git a/openerp/addons/base/i18n/ja.po b/openerp/addons/base/i18n/ja.po index 2d6310e5312..b3f7126abf8 100644 --- a/openerp/addons/base/i18n/ja.po +++ b/openerp/addons/base/i18n/ja.po @@ -5431,7 +5431,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/kk.po b/openerp/addons/base/i18n/kk.po index 1df9844334b..2473306dac8 100644 --- a/openerp/addons/base/i18n/kk.po +++ b/openerp/addons/base/i18n/kk.po @@ -5431,7 +5431,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/ko.po b/openerp/addons/base/i18n/ko.po index 0025fb970e6..d4552dceb23 100644 --- a/openerp/addons/base/i18n/ko.po +++ b/openerp/addons/base/i18n/ko.po @@ -5457,7 +5457,7 @@ msgstr "번역" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/lt.po b/openerp/addons/base/i18n/lt.po index 2a31023df0f..f497c904fbd 100644 --- a/openerp/addons/base/i18n/lt.po +++ b/openerp/addons/base/i18n/lt.po @@ -5464,7 +5464,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/lt_LT.po b/openerp/addons/base/i18n/lt_LT.po index 7aee4518a19..5c98c806928 100644 --- a/openerp/addons/base/i18n/lt_LT.po +++ b/openerp/addons/base/i18n/lt_LT.po @@ -4618,7 +4618,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/lv.po b/openerp/addons/base/i18n/lv.po index cd1ef4c77fe..8b654b76800 100644 --- a/openerp/addons/base/i18n/lv.po +++ b/openerp/addons/base/i18n/lv.po @@ -5514,7 +5514,7 @@ msgstr "Tulkojumi" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Ciparu vietas" #. module: base diff --git a/openerp/addons/base/i18n/mk.po b/openerp/addons/base/i18n/mk.po index bb8f47fcf7c..d9b5395a888 100644 --- a/openerp/addons/base/i18n/mk.po +++ b/openerp/addons/base/i18n/mk.po @@ -5431,7 +5431,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/mn.po b/openerp/addons/base/i18n/mn.po index 12c8460790f..fa355ed7b11 100644 --- a/openerp/addons/base/i18n/mn.po +++ b/openerp/addons/base/i18n/mn.po @@ -5533,7 +5533,7 @@ msgstr "Орчуулгууд" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Тоон дугаарын урт" #. module: base diff --git a/openerp/addons/base/i18n/nb.po b/openerp/addons/base/i18n/nb.po index c62673f2b19..17bc1c0e472 100644 --- a/openerp/addons/base/i18n/nb.po +++ b/openerp/addons/base/i18n/nb.po @@ -5530,7 +5530,7 @@ msgstr "Oversettelser" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Bunnfyll" #. module: base diff --git a/openerp/addons/base/i18n/nl.po b/openerp/addons/base/i18n/nl.po index 2bb60f29b38..831941c72a6 100644 --- a/openerp/addons/base/i18n/nl.po +++ b/openerp/addons/base/i18n/nl.po @@ -5702,7 +5702,7 @@ msgstr "Vertalingen" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Nummer verspringing" #. module: base diff --git a/openerp/addons/base/i18n/nl_BE.po b/openerp/addons/base/i18n/nl_BE.po index 09b17071edd..aba44535fa2 100644 --- a/openerp/addons/base/i18n/nl_BE.po +++ b/openerp/addons/base/i18n/nl_BE.po @@ -5447,7 +5447,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/nl_NL.po b/openerp/addons/base/i18n/nl_NL.po index 704c25a9d46..eeef0f9010e 100644 --- a/openerp/addons/base/i18n/nl_NL.po +++ b/openerp/addons/base/i18n/nl_NL.po @@ -4796,7 +4796,7 @@ msgstr "Vertalingen" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Nummer verspringing" #. module: base diff --git a/openerp/addons/base/i18n/pl.po b/openerp/addons/base/i18n/pl.po index 9b8f0c8769c..417976cebd6 100644 --- a/openerp/addons/base/i18n/pl.po +++ b/openerp/addons/base/i18n/pl.po @@ -5612,7 +5612,7 @@ msgstr "Tłumaczenia" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Liczba cyfr" #. module: base diff --git a/openerp/addons/base/i18n/pt.po b/openerp/addons/base/i18n/pt.po index 88b097ffe71..03f8b93ede1 100644 --- a/openerp/addons/base/i18n/pt.po +++ b/openerp/addons/base/i18n/pt.po @@ -5591,7 +5591,7 @@ msgstr "Traduções" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Dígitos do número" #. module: base diff --git a/openerp/addons/base/i18n/pt_BR.po b/openerp/addons/base/i18n/pt_BR.po index 254c642a060..e8c5a66dada 100644 --- a/openerp/addons/base/i18n/pt_BR.po +++ b/openerp/addons/base/i18n/pt_BR.po @@ -5687,7 +5687,7 @@ msgstr "Traduções" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Preencher número" #. module: base diff --git a/openerp/addons/base/i18n/ro.po b/openerp/addons/base/i18n/ro.po index 7f6e34b2edc..5d1f4e6012d 100644 --- a/openerp/addons/base/i18n/ro.po +++ b/openerp/addons/base/i18n/ro.po @@ -5555,7 +5555,7 @@ msgstr "Traduceri" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/ru.po b/openerp/addons/base/i18n/ru.po index 48133981214..33388d00882 100644 --- a/openerp/addons/base/i18n/ru.po +++ b/openerp/addons/base/i18n/ru.po @@ -5689,7 +5689,7 @@ msgstr "Переводы" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Выравнивание чисел" #. module: base diff --git a/openerp/addons/base/i18n/sk.po b/openerp/addons/base/i18n/sk.po index df5f44b9ef4..267dc5a9223 100644 --- a/openerp/addons/base/i18n/sk.po +++ b/openerp/addons/base/i18n/sk.po @@ -5598,7 +5598,7 @@ msgstr "Preklady" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Zarovanie čísla" #. module: base diff --git a/openerp/addons/base/i18n/sl.po b/openerp/addons/base/i18n/sl.po index 22d06500f88..5e6d5eb5119 100644 --- a/openerp/addons/base/i18n/sl.po +++ b/openerp/addons/base/i18n/sl.po @@ -5650,7 +5650,7 @@ msgstr "Prevodi" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Zapolnitev številke" #. module: base diff --git a/openerp/addons/base/i18n/sq.po b/openerp/addons/base/i18n/sq.po index 4d38cd56221..bb97ede3852 100644 --- a/openerp/addons/base/i18n/sq.po +++ b/openerp/addons/base/i18n/sq.po @@ -5430,7 +5430,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/sr.po b/openerp/addons/base/i18n/sr.po index 04a1487c320..b174a0b5a2b 100644 --- a/openerp/addons/base/i18n/sr.po +++ b/openerp/addons/base/i18n/sr.po @@ -5575,7 +5575,7 @@ msgstr "Prevodi" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Dopunjavanje brojeva" #. module: base diff --git a/openerp/addons/base/i18n/sr@latin.po b/openerp/addons/base/i18n/sr@latin.po index a545d3854a8..2aeaeb0279b 100644 --- a/openerp/addons/base/i18n/sr@latin.po +++ b/openerp/addons/base/i18n/sr@latin.po @@ -5431,7 +5431,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/sv.po b/openerp/addons/base/i18n/sv.po index 5dd00cab0ba..9422185f5da 100644 --- a/openerp/addons/base/i18n/sv.po +++ b/openerp/addons/base/i18n/sv.po @@ -5624,7 +5624,7 @@ msgstr "Översättningar" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Numerisk utfyllnad" #. module: base diff --git a/openerp/addons/base/i18n/th.po b/openerp/addons/base/i18n/th.po index d785c5d635b..312b25c8e63 100644 --- a/openerp/addons/base/i18n/th.po +++ b/openerp/addons/base/i18n/th.po @@ -5431,7 +5431,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/tlh.po b/openerp/addons/base/i18n/tlh.po index dede310a722..226f568ed46 100644 --- a/openerp/addons/base/i18n/tlh.po +++ b/openerp/addons/base/i18n/tlh.po @@ -5430,7 +5430,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/tr.po b/openerp/addons/base/i18n/tr.po index a1661ed041e..4311bcb01a8 100644 --- a/openerp/addons/base/i18n/tr.po +++ b/openerp/addons/base/i18n/tr.po @@ -5637,7 +5637,7 @@ msgstr "Çeviriler" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Numara dolgusu" #. module: base diff --git a/openerp/addons/base/i18n/uk.po b/openerp/addons/base/i18n/uk.po index a024978394c..6c1f6ffeb02 100644 --- a/openerp/addons/base/i18n/uk.po +++ b/openerp/addons/base/i18n/uk.po @@ -5495,7 +5495,7 @@ msgstr "Переклади" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Вирівнювання номерів" #. module: base diff --git a/openerp/addons/base/i18n/uk_UA.po b/openerp/addons/base/i18n/uk_UA.po index c1923fd44a9..c984308a4de 100644 --- a/openerp/addons/base/i18n/uk_UA.po +++ b/openerp/addons/base/i18n/uk_UA.po @@ -4636,7 +4636,7 @@ msgstr "Переклади" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "Вирівнювання номерів" #. module: base diff --git a/openerp/addons/base/i18n/ur.po b/openerp/addons/base/i18n/ur.po index 2457121dad1..4deaed2489c 100644 --- a/openerp/addons/base/i18n/ur.po +++ b/openerp/addons/base/i18n/ur.po @@ -5431,7 +5431,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/vi.po b/openerp/addons/base/i18n/vi.po index 417c64daba6..ba03de09502 100644 --- a/openerp/addons/base/i18n/vi.po +++ b/openerp/addons/base/i18n/vi.po @@ -5468,7 +5468,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/zh_CN.po b/openerp/addons/base/i18n/zh_CN.po index ccc8619e189..a633854008f 100644 --- a/openerp/addons/base/i18n/zh_CN.po +++ b/openerp/addons/base/i18n/zh_CN.po @@ -5471,7 +5471,7 @@ msgstr "翻译" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "数字位数" #. module: base diff --git a/openerp/addons/base/i18n/zh_HK.po b/openerp/addons/base/i18n/zh_HK.po index 75dd21f04ff..36c46a3b93c 100644 --- a/openerp/addons/base/i18n/zh_HK.po +++ b/openerp/addons/base/i18n/zh_HK.po @@ -5431,7 +5431,7 @@ msgstr "" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/i18n/zh_TW.po b/openerp/addons/base/i18n/zh_TW.po index 53610346f81..c6b6ac26afa 100644 --- a/openerp/addons/base/i18n/zh_TW.po +++ b/openerp/addons/base/i18n/zh_TW.po @@ -5447,7 +5447,7 @@ msgstr "翻譯" #. module: base #: field:ir.sequence,padding:0 -msgid "Number padding" +msgid "Number Padding" msgstr "" #. module: base diff --git a/openerp/addons/base/ir/ir_sequence.py b/openerp/addons/base/ir/ir_sequence.py index 4d10eefe75e..b0995c914d0 100644 --- a/openerp/addons/base/ir/ir_sequence.py +++ b/openerp/addons/base/ir/ir_sequence.py @@ -65,7 +65,7 @@ class ir_sequence(openerp.osv.osv.osv): 'suffix': openerp.osv.fields.char('Suffix', size=64, help="Suffix value of the record for the sequence"), 'number_next': openerp.osv.fields.integer('Next Number', required=True, help="Next number of this sequence"), 'number_increment': openerp.osv.fields.integer('Increment Number', required=True, help="The next number of the sequence will be incremented by this number"), - 'padding' : openerp.osv.fields.integer('Number padding', required=True, help="OpenERP will automatically adds some '0' on the left of the 'Next Number' to get the required padding size."), + 'padding' : openerp.osv.fields.integer('Number Padding', required=True, help="OpenERP will automatically adds some '0' on the left of the 'Next Number' to get the required padding size."), 'company_id': openerp.osv.fields.many2one('res.company', 'Company'), } _defaults = { From 538cc0e92f9fbc993bec5a224de4c3f38b9a13e6 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Wed, 28 Sep 2011 16:15:20 +0200 Subject: [PATCH 023/161] [FIX] ir_sequence: typo in read(). bzr revid: vmt@openerp.com-20110928141520-9yx9sogoetizb9nn --- openerp/addons/base/ir/ir_sequence.py | 2 +- tests/test_ir_sequence.py | 143 +++++++++++++++----------- 2 files changed, 86 insertions(+), 59 deletions(-) diff --git a/openerp/addons/base/ir/ir_sequence.py b/openerp/addons/base/ir/ir_sequence.py index b0995c914d0..34a4b0144eb 100644 --- a/openerp/addons/base/ir/ir_sequence.py +++ b/openerp/addons/base/ir/ir_sequence.py @@ -104,7 +104,7 @@ class ir_sequence(openerp.osv.osv.osv): def write(self, cr, uid, ids, values, context=None): ids = ids if isinstance(ids, (list, tuple)) else [ids] new_implementation = values.get('implementation') - rows = self.read(cr, uid, ids, ['id,' 'implementation', + rows = self.read(cr, uid, ids, ['implementation', 'number_increment', 'number_next'], context) super(ir_sequence, self).write(cr, uid, ids, values, context) diff --git a/tests/test_ir_sequence.py b/tests/test_ir_sequence.py index 0fc7aec5b50..13c40dd6eb3 100644 --- a/tests/test_ir_sequence.py +++ b/tests/test_ir_sequence.py @@ -33,51 +33,43 @@ class test_ir_sequence_standard(unittest2.TestCase): def test_ir_sequence_create(self): """ Try to create a sequence object. """ cr = cursor() - try: - d = dict(code='test_sequence_type', name='Test sequence type') - c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) - assert c - d = dict(code='test_sequence_type', name='Test sequence') - c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) - assert c - cr.commit() - finally: - cr.close() + d = dict(code='test_sequence_type', name='Test sequence type') + c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + assert c + d = dict(code='test_sequence_type', name='Test sequence') + c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + assert c + cr.commit() + cr.close() def test_ir_sequence_search(self): """ Try a search. """ cr = cursor() - try: - ids = registry('ir.sequence').search(cr, ADMIN_USER_ID, [], {}) - assert ids - cr.commit() - finally: - cr.close() + ids = registry('ir.sequence').search(cr, ADMIN_USER_ID, [], {}) + assert ids + cr.commit() + cr.close() def test_ir_sequence_draw(self): """ Try to draw a number. """ cr = cursor() - try: - n = registry('ir.sequence').get(cr, ADMIN_USER_ID, 'test_sequence_type', {}) - assert n - cr.commit() - finally: - cr.close() + n = registry('ir.sequence').get(cr, ADMIN_USER_ID, 'test_sequence_type', {}) + assert n + cr.commit() + cr.close() def test_ir_sequence_draw_twice(self): """ Try to draw a number from two transactions. """ cr0 = cursor() cr1 = cursor() - try: - n0 = registry('ir.sequence').get(cr0, ADMIN_USER_ID, 'test_sequence_type', {}) - assert n0 - n1 = registry('ir.sequence').get(cr1, ADMIN_USER_ID, 'test_sequence_type', {}) - assert n1 - cr0.commit() - cr1.commit() - finally: - cr0.close() - cr1.close() + n0 = registry('ir.sequence').get(cr0, ADMIN_USER_ID, 'test_sequence_type', {}) + assert n0 + n1 = registry('ir.sequence').get(cr1, ADMIN_USER_ID, 'test_sequence_type', {}) + assert n1 + cr0.commit() + cr1.commit() + cr0.close() + cr1.close() class test_ir_sequence_no_gap(unittest2.TestCase): """ Copy of the previous tests for a 'No gap' sequence. """ @@ -85,27 +77,23 @@ class test_ir_sequence_no_gap(unittest2.TestCase): def test_ir_sequence_create_no_gap(self): """ Try to create a sequence object. """ cr = cursor() - try: - d = dict(code='test_sequence_type_2', name='Test sequence type') - c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) - assert c - d = dict(code='test_sequence_type_2', name='Test sequence', - implementation='no_gap') - c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) - assert c - cr.commit() - finally: - cr.close() + d = dict(code='test_sequence_type_2', name='Test sequence type') + c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + assert c + d = dict(code='test_sequence_type_2', name='Test sequence', + implementation='no_gap') + c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + assert c + cr.commit() + cr.close() def test_ir_sequence_draw_no_gap(self): """ Try to draw a number. """ cr = cursor() - try: - n = registry('ir.sequence').get(cr, ADMIN_USER_ID, 'test_sequence_type_2', {}) - assert n - cr.commit() - finally: - cr.close() + n = registry('ir.sequence').get(cr, ADMIN_USER_ID, 'test_sequence_type_2', {}) + assert n + cr.commit() + cr.close() def test_ir_sequence_draw_twice_no_gap(self): """ Try to draw a number from two transactions. @@ -113,15 +101,54 @@ class test_ir_sequence_no_gap(unittest2.TestCase): """ cr0 = cursor() cr1 = cursor() - try: - msg_re = '^could not obtain lock on row in relation "ir_sequence"$' - with self.assertRaisesRegexp(psycopg2.OperationalError, msg_re): - n0 = registry('ir.sequence').get(cr0, ADMIN_USER_ID, 'test_sequence_type_2', {}) - assert n0 - n1 = registry('ir.sequence').get(cr1, ADMIN_USER_ID, 'test_sequence_type_2', {}) - finally: - cr0.close() - cr1.close() + msg_re = '^could not obtain lock on row in relation "ir_sequence"$' + with self.assertRaisesRegexp(psycopg2.OperationalError, msg_re): + n0 = registry('ir.sequence').get(cr0, ADMIN_USER_ID, 'test_sequence_type_2', {}) + assert n0 + n1 = registry('ir.sequence').get(cr1, ADMIN_USER_ID, 'test_sequence_type_2', {}) + cr0.close() + cr1.close() + +class test_ir_sequence_change_implementation(unittest2.TestCase): + """ Create sequence objects and change their ``implementation`` field. """ + + def test_ir_sequence_1_create(self): + """ Try to create a sequence object. """ + cr = cursor() + d = dict(code='test_sequence_type_3', name='Test sequence type') + c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + assert c + d = dict(code='test_sequence_type_3', name='Test sequence') + c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + assert c + d = dict(code='test_sequence_type_4', name='Test sequence type') + c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + assert c + d = dict(code='test_sequence_type_4', name='Test sequence', + implementation='no_gap') + c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + assert c + cr.commit() + cr.close() + + def test_ir_sequence_2_write(self): + cr = cursor() + ids = registry('ir.sequence').search(cr, ADMIN_USER_ID, + [('code', 'in', ['test_sequence_type_3', 'test_sequence_type_4'])], {}) + registry('ir.sequence').write(cr, ADMIN_USER_ID, ids, + {'implementation': 'standard'}, {}) + registry('ir.sequence').write(cr, ADMIN_USER_ID, ids, + {'implementation': 'no_gap'}, {}) + cr.commit() + cr.close() + + def test_ir_sequence_3_unlink(self): + cr = cursor() + ids = registry('ir.sequence').search(cr, ADMIN_USER_ID, + [('code', 'in', ['test_sequence_type_3', 'test_sequence_type_4'])], {}) + registry('ir.sequence').unlink(cr, ADMIN_USER_ID, ids, {}) + cr.commit() + cr.close() if __name__ == '__main__': From b917742f15c6c801120d49277e2d8b846c9e7f36 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Wed, 28 Sep 2011 17:17:04 +0200 Subject: [PATCH 024/161] [IMP] ir_sequence: added a simple test. bzr revid: vmt@openerp.com-20110928151704-tqsr5h8zqs0vr32f --- tests/test_ir_sequence.py | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tests/test_ir_sequence.py b/tests/test_ir_sequence.py index 13c40dd6eb3..8a4731d524f 100644 --- a/tests/test_ir_sequence.py +++ b/tests/test_ir_sequence.py @@ -6,6 +6,7 @@ # OPENERP_DATABASE=yy nosetests tests/test_ir_sequence.py # > OPENERP_ADDONS_PATH='../../../addons/trunk' OPENERP_PORT=8069 \ # OPENERP_DATABASE=yy PYTHONPATH=../:. unit2 test_ir_sequence +# This assume an existing database. import os import psycopg2 import time @@ -150,6 +151,47 @@ class test_ir_sequence_change_implementation(unittest2.TestCase): cr.commit() cr.close() +class test_ir_sequence_generate(unittest2.TestCase): + """ Create sequence objects and generate some values. """ + + def test_ir_sequence_create(self): + """ Try to create a sequence object. """ + cr = cursor() + d = dict(code='test_sequence_type_5', name='Test sequence type') + c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + assert c + d = dict(code='test_sequence_type_5', name='Test sequence') + c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + assert c + cr.commit() + cr.close() + + cr = cursor() + f = lambda *a: registry('ir.sequence').get(cr, ADMIN_USER_ID, 'test_sequence_type_5', {}) + assert all(str(x) == f() for x in xrange(1,1000)) + cr.commit() + cr.close() + + def test_ir_sequence_create_no_gap(self): + """ Try to create a sequence object. """ + cr = cursor() + d = dict(code='test_sequence_type_6', name='Test sequence type', + implementation='no_gap') + c = registry('ir.sequence.type').create(cr, ADMIN_USER_ID, d, {}) + assert c + d = dict(code='test_sequence_type_6', name='Test sequence') + c = registry('ir.sequence').create(cr, ADMIN_USER_ID, d, {}) + assert c + cr.commit() + cr.close() + + cr = cursor() + f = lambda *a: registry('ir.sequence').get(cr, ADMIN_USER_ID, 'test_sequence_type_6', {}) + assert all(str(x) == f() for x in xrange(1,1000)) + cr.commit() + cr.close() + + if __name__ == '__main__': unittest2.main() From c6e77707ee07cae611ae18176103300e94e7463d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 29 Sep 2011 11:02:05 +0200 Subject: [PATCH 025/161] [FIX] match first form header only so that we get the header for current form not sub-forms bzr revid: xmo@openerp.com-20110929090205-0vn4dt4qixao5us1 --- addons/web/static/src/js/view_form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/src/js/view_form.js b/addons/web/static/src/js/view_form.js index c9dcb65cba9..e39b1966556 100644 --- a/addons/web/static/src/js/view_form.js +++ b/addons/web/static/src/js/view_form.js @@ -89,7 +89,7 @@ openerp.web.FormView = openerp.web.View.extend( /** @lends openerp.web.FormView# _.each(this.widgets, function(w) { w.start(); }); - this.$form_header = this.$element.find('.oe_form_header'); + this.$form_header = this.$element.find('.oe_form_header:first'); this.$form_header.find('div.oe_form_pager button[data-pager-action]').click(function() { var action = $(this).data('pager-action'); self.on_pager_action(action); From a658311000e9ad5a7d078a562da3a9e716f2d4f3 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Thu, 29 Sep 2011 14:17:32 +0200 Subject: [PATCH 026/161] [imp] now uses a global connector for connection to OpenERP server bzr revid: nicolas.vanhoren@openerp.com-20110929121732-xydsj26xw9fyn1hr --- addons/web/common/dispatch.py | 7 +++++++ addons/web/common/openerplib/main.py | 10 +++++++++- addons/web/common/session.py | 10 ++++------ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/addons/web/common/dispatch.py b/addons/web/common/dispatch.py index 7a293c8228b..57e45fa594e 100644 --- a/addons/web/common/dispatch.py +++ b/addons/web/common/dispatch.py @@ -311,6 +311,13 @@ class Root(object): def __init__(self, options): self.root = werkzeug.urls.Href('/web/webclient/home') self.config = options + + if self.config.backend == 'local': + conn = openerplib.get_connector(protocol='local') + else: + conn = openerplib.get_connector(hostname=self.config.server_host, + port=self.config.server_port) + self.config.connector = conn self.session_cookie = 'sessionid' self.addons = {} diff --git a/addons/web/common/openerplib/main.py b/addons/web/common/openerplib/main.py index ffe7d3c2d8b..b09e9f9d72f 100644 --- a/addons/web/common/openerplib/main.py +++ b/addons/web/common/openerplib/main.py @@ -71,6 +71,14 @@ class Connector(object): self.hostname = hostname self.port = port + def get_service(self, service_name): + """ + Returns a Service instance to allow easy manipulation of one of the services offered by the remote server. + + :param service_name: The name of the service. + """ + return Service(self, service_name) + class XmlRPCConnector(Connector): """ A type of connector that uses the XMLRPC protocol. @@ -321,7 +329,7 @@ class Connection(object): :param service_name: The name of the service. """ - return Service(self.connector, service_name) + return self.connector.get_service(service_name) class AuthenticationError(Exception): """ diff --git a/addons/web/common/session.py b/addons/web/common/session.py index c06763bebe2..d4265851acc 100644 --- a/addons/web/common/session.py +++ b/addons/web/common/session.py @@ -5,6 +5,9 @@ import time import openerplib import nonliterals + +import logging +_logger = logging.getLogger(__name__) #---------------------------------------------------------- # OpenERPSession RPC openerp backend access #---------------------------------------------------------- @@ -41,12 +44,7 @@ class OpenERPSession(object): self.client_timezone = False def build_connection(self): - if self.config.backend == 'local': - conn = openerplib.get_connection(protocol='local', database=self._db, - login=self._login, user_id=self._uid, password=self._password) - else: - conn = openerplib.get_connection(hostname=self.config.server_host, - port=self.config.server_port, database=self._db, login=self._login, + conn = openerplib.Connection(self.config.connector, database=self._db, login=self._login, user_id=self._uid, password=self._password) return conn From dc993b507ecf876a150c054ff0c4b8823e0314f2 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Thu, 29 Sep 2011 14:27:53 +0200 Subject: [PATCH 027/161] [IMP] ir_sequence: change API, deprecate old one. bzr revid: vmt@openerp.com-20110929122753-19middna4b782tcy --- openerp/addons/base/ir/ir_sequence.py | 93 ++++++++++++++++----------- 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/openerp/addons/base/ir/ir_sequence.py b/openerp/addons/base/ir/ir_sequence.py index 34a4b0144eb..3a3a6d4e5e2 100644 --- a/openerp/addons/base/ir/ir_sequence.py +++ b/openerp/addons/base/ir/ir_sequence.py @@ -19,10 +19,13 @@ # ############################################################################## +import logging import time import openerp +_logger = logging.getLogger('ir_sequence') + class ir_sequence_type(openerp.osv.osv.osv): _name = 'ir.sequence.type' _order = 'name' @@ -39,9 +42,6 @@ def _code_get(self, cr, uid, context={}): cr.execute('select code, name from ir_sequence_type') return cr.fetchall() -IMPLEMENTATION_SELECTION = \ - [('standard', 'Standard'), ('no_gap', 'No gap')] - class ir_sequence(openerp.osv.osv.osv): """ Sequence model. @@ -56,7 +56,8 @@ class ir_sequence(openerp.osv.osv.osv): 'name': openerp.osv.fields.char('Name', size=64, required=True), 'code': openerp.osv.fields.selection(_code_get, 'Code', size=64, required=True), 'implementation': openerp.osv.fields.selection( # TODO update the view - IMPLEMENTATION_SELECTION, 'Implementation', required=True, + [('standard', 'Standard'), ('no_gap', 'No gap')], + 'Implementation', required=True, help="Two sequence object implementations are offered: Standard " "and 'No gap'. The later is slower than the former but forbids any" " gap in the sequence (while they are possible in the former)."), @@ -144,53 +145,71 @@ class ir_sequence(openerp.osv.osv.osv): 'sec': time.strftime('%S', t), } - # TODO rename 'test' to 'code_or_id' in account/sequence. + def next_by_id(self, cr, uid, sequence_id, context=None): + """ Draw an interpolated string using the specified sequence.""" + self.check_read(cr, uid) + res = self._select_by_code_or_id(cr, uid, sequence_id, + 'id', False, context) + return self._next(cr, uid, res, context) + + def next_by_code(self, cr, uid, sequence_code, context=None): + """ Draw an interpolated string using the specified sequence.""" + self.check_read(cr, uid) + res = self._select_by_code_or_id(cr, uid, sequence_code, + 'code', False, context) + return self._next(cr, uid, res, context) + def get_id(self, cr, uid, sequence_code_or_id, code_or_id='id', context=None): """ Draw an interpolated string using the specified sequence. The sequence to use is specified by the ``sequence_code_or_id`` argument, which can be a code or an id (as controlled by the - ``code_or_id`` argument. + ``code_or_id`` argument. This method is deprecated. """ - self.check_read(cr, uid) - res = self._select_by_code_or_id(cr, uid, sequence_code_or_id, - code_or_id, False, context) - - if not res: - return False - - if res['implementation'] == 'standard': - cr.execute(""" - SELECT nextval('ir_sequence_%03d') - """ % res['id']) - res['number_next'] = cr.fetchone() + _logger.warning("ir_sequence.get() and ir_sequence.get_id() are deprecated. " + "Please use ir_sequence.next_by_code() or ir_sequence.next_by_id().") + if code_or_id == 'id': + return self.next_by_id(cr, uid, sequence_code_or_id, context) else: - # Read again with FOR UPDATE NO WAIT. - res = self._select_by_code_or_id(cr, uid, sequence_code_or_id, - code_or_id, True, context) - cr.execute(""" - UPDATE ir_sequence - SET number_next=number_next+number_increment - WHERE id=%s - """, (res['id'],)) - - d = self._interpolation_dict() - interpolated_prefix = self._interpolate(res['prefix'], d) - interpolated_suffix = self._interpolate(res['suffix'], d) - if res['number_next']: - return interpolated_prefix + '%%0%sd' % res['padding'] % \ - res['number_next'] + interpolated_suffix - else: - # TODO what is this case used for ? - return interpolated_prefix + interpolated_suffix + return self.next_by_code(cr, uid, sequence_code_or_id, context) def get(self, cr, uid, code, context=None): """ Draw an interpolated string using the specified sequence. - The sequence to use is specified by its code. + The sequence to use is specified by its code. This method is + deprecated. """ return self.get_id(cr, uid, code, 'code', context) + def _next(self, cr, uid, sequence, context=None): + if not sequence: + return False + + if sequence['implementation'] == 'standard': + cr.execute(""" + SELECT nextval('ir_sequence_%03d') + """ % sequence['id']) + sequence['number_next'] = cr.fetchone() + else: + # Read again with FOR UPDATE NO WAIT. + sequence = self._select_by_code_or_id(cr, uid, sequence['id'], + 'id', True, context) + cr.execute(""" + UPDATE ir_sequence + SET number_next=number_next+number_increment + WHERE id=%s + """, (sequence['id'],)) + + d = self._interpolation_dict() + interpolated_prefix = self._interpolate(sequence['prefix'], d) + interpolated_suffix = self._interpolate(sequence['suffix'], d) + if sequence['number_next']: + return interpolated_prefix + '%%0%sd' % sequence['padding'] % \ + sequence['number_next'] + interpolated_suffix + else: + # TODO what is this case used for ? + return interpolated_prefix + interpolated_suffix + def _select_by_code_or_id(self, cr, uid, sequence_code_or_id, code_or_id, for_update_no_wait, context=None): """ Read a sequence object. From 6c90db2ddee959e90bcffca7feb53d3d10e2b404 Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Thu, 29 Sep 2011 14:48:58 +0200 Subject: [PATCH 028/161] [IMP] ir_sequence: adapt addons code to server changes. bzr revid: vmt@openerp.com-20110929124858-9nr2gbpuxc6k7ofx --- addons/account/sequence.py | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/addons/account/sequence.py b/addons/account/sequence.py index 1683e5feb06..30e8d62a350 100644 --- a/addons/account/sequence.py +++ b/addons/account/sequence.py @@ -46,23 +46,18 @@ class ir_sequence(osv.osv): 'fiscal_ids': fields.one2many('account.sequence.fiscalyear', 'sequence_main_id', 'Sequences') } - def get_id(self, cr, uid, sequence_id, test='id', context=None): - if context is None: - context = {} - cr.execute('select id from ir_sequence where ' - + test + '=%s and active=%s', (sequence_id, True,)) - res = cr.dictfetchone() - if res: - for line in self.browse(cr, uid, res['id'], - context=context).fiscal_ids: - if line.fiscalyear_id.id == context.get('fiscalyear_id', False): - return super(ir_sequence, self).get_id(cr, uid, - line.sequence_id.id, - test="id", - context=context) - return super(ir_sequence, self).get_id(cr, uid, sequence_id, test, - context=context) + + def _select_by_code_or_id(self, cr, uid, sequence_code_or_id, code_or_id, + for_update_no_wait, context=None): + res = super(ir_sequence, self)._select_by_code_or_id(cr, uid, + sequence_code_or_id, code_or_id, False, context) + if not res: + return + for line in self.browse(cr, uid, res['id'], context).fiscal_ids: + if line.fiscalyear_id.id == context.get('fiscalyear_id'): + return super(ir_sequence, self)._select_by_code_or_id(cr, uid, + line.sequence_id.id, 'id', False, context) ir_sequence() -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 22b1bb8abb0cb7148d0cbeadea1fe0aba2e11f97 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 29 Sep 2011 15:07:01 +0200 Subject: [PATCH 029/161] [FIX] do not remove 'multi=True' actions in fields_view_get for tree view fields_view_get removed multi=True actions from the result of ir_values.get_actions('client_action_multi', ...), so that multi actions would not be displayed in the form view's sidebar in the GTK client. The web client has a sidebar in both cases, the GTK client just ignores 'toolbar' key if not in tree view, so don't remove 'multi' actions in tree view toolbar, to avoid having to perform one more RPC call (explicit ir_values.get) in web client. lp bug: https://launchpad.net/bugs/856378 fixed bzr revid: xmo@openerp.com-20110929130701-65ubx1o0swk889nl --- openerp/osv/orm.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 5a18b893910..7e3ffa7fcb0 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -2069,8 +2069,9 @@ class BaseModel(object): context) resprint = map(clean, resprint) resaction = map(clean, resaction) - resaction = filter(lambda x: not x.get('multi', False), resaction) - resprint = filter(lambda x: not x.get('multi', False), resprint) + if view_type != 'tree': + resaction = filter(lambda x: not x.get('multi'), resaction) + resprint = filter(lambda x: not x.get('multi'), resprint) resrelate = map(lambda x: x[2], resrelate) for x in resprint + resaction + resrelate: From bd341cc6fee241aa45f71b0770527df683e0472a Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Thu, 29 Sep 2011 15:22:54 +0200 Subject: [PATCH 030/161] [IMP] ir_sequence: call it with the new methods. bzr revid: vmt@openerp.com-20110929132254-eevlq6t9d6i6um7z --- addons/account/account.py | 2 +- addons/account/account_bank_statement.py | 4 ++-- addons/account/account_cash_statement.py | 4 ++-- addons/account/account_move_line.py | 2 +- addons/account_sequence/account_sequence.py | 2 +- addons/account_voucher/account_voucher.py | 2 +- addons/point_of_sale/wizard/pos_open_statement.py | 4 ++-- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/addons/account/account.py b/addons/account/account.py index 34306b703aa..538f9ed3b4e 100644 --- a/addons/account/account.py +++ b/addons/account/account.py @@ -1214,7 +1214,7 @@ class account_move(osv.osv): else: if journal.sequence_id: c = {'fiscalyear_id': move.period_id.fiscalyear_id.id} - new_name = obj_sequence.get_id(cr, uid, journal.sequence_id.id, context=c) + new_name = obj_sequence.next_by_id(cr, uid, journal.sequence_id.id, c) else: raise osv.except_osv(_('Error'), _('No sequence defined on the journal !')) diff --git a/addons/account/account_bank_statement.py b/addons/account/account_bank_statement.py index 4cc2ed89786..98051a319fd 100644 --- a/addons/account/account_bank_statement.py +++ b/addons/account/account_bank_statement.py @@ -340,9 +340,9 @@ class account_bank_statement(osv.osv): else: if st.journal_id.sequence_id: c = {'fiscalyear_id': st.period_id.fiscalyear_id.id} - st_number = obj_seq.get_id(cr, uid, st.journal_id.sequence_id.id, context=c) + st_number = obj_seq.next_by_id(cr, uid, st.journal_id.sequence_id.id, context=c) else: - st_number = obj_seq.get(cr, uid, 'account.bank.statement') + st_number = obj_seq.next_by_code(cr, uid, 'account.bank.statement') for line in st.move_line_ids: if line.state <> 'valid': diff --git a/addons/account/account_cash_statement.py b/addons/account/account_cash_statement.py index dc78d19bab4..ebc97fe8a84 100644 --- a/addons/account/account_cash_statement.py +++ b/addons/account/account_cash_statement.py @@ -294,9 +294,9 @@ class account_cash_statement(osv.osv): if statement.name and statement.name == '/': if statement.journal_id.sequence_id: c = {'fiscalyear_id': statement.period_id.fiscalyear_id.id} - st_number = obj_seq.get_id(cr, uid, statement.journal_id.sequence_id.id, context=c) + st_number = obj_seq.next_by_id(cr, uid, statement.journal_id.sequence_id.id, context=c) else: - st_number = obj_seq.get(cr, uid, 'account.cash.statement') + st_number = obj_seq.next_by_code(cr, uid, 'account.cash.statement') vals.update({ 'name': st_number }) diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index 1322226bfb6..ce349fc4f4e 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -1221,7 +1221,7 @@ class account_move_line(osv.osv): vals['move_id'] = res[0] if not vals.get('move_id', False): if journal.sequence_id: - #name = self.pool.get('ir.sequence').get_id(cr, uid, journal.sequence_id.id) + #name = self.pool.get('ir.sequence').next_by_id(cr, uid, journal.sequence_id.id) v = { 'date': vals.get('date', time.strftime('%Y-%m-%d')), 'period_id': context['period_id'], diff --git a/addons/account_sequence/account_sequence.py b/addons/account_sequence/account_sequence.py index 1649a8890fa..8b87b3f40ae 100644 --- a/addons/account_sequence/account_sequence.py +++ b/addons/account_sequence/account_sequence.py @@ -35,7 +35,7 @@ class account_move(osv.osv): seq_no = False for move in self.browse(cr, uid, ids, context=context): if move.journal_id.internal_sequence_id: - seq_no = obj_sequence.get_id(cr, uid, move.journal_id.internal_sequence_id.id, context=context) + seq_no = obj_sequence.next_by_id(cr, uid, move.journal_id.internal_sequence_id.id, context=context) if seq_no: self.write(cr, uid, [move.id], {'internal_sequence_number': seq_no}) return res diff --git a/addons/account_voucher/account_voucher.py b/addons/account_voucher/account_voucher.py index da9dbe87893..005e5d9ab46 100644 --- a/addons/account_voucher/account_voucher.py +++ b/addons/account_voucher/account_voucher.py @@ -674,7 +674,7 @@ class account_voucher(osv.osv): if inv.number: name = inv.number elif inv.journal_id.sequence_id: - name = seq_obj.get_id(cr, uid, inv.journal_id.sequence_id.id) + name = seq_obj.next_by_id(cr, uid, inv.journal_id.sequence_id.id) else: raise osv.except_osv(_('Error !'), _('Please define a sequence on the journal !')) if not inv.reference: diff --git a/addons/point_of_sale/wizard/pos_open_statement.py b/addons/point_of_sale/wizard/pos_open_statement.py index 038ca3b6990..47c5348943b 100644 --- a/addons/point_of_sale/wizard/pos_open_statement.py +++ b/addons/point_of_sale/wizard/pos_open_statement.py @@ -53,9 +53,9 @@ class pos_open_statement(osv.osv_memory): continue if journal.sequence_id: - number = sequence_obj.get_id(cr, uid, journal.sequence_id.id) + number = sequence_obj.next_by_id(cr, uid, journal.sequence_id.id) else: - number = sequence_obj.get(cr, uid, 'account.cash.statement') + number = sequence_obj.next_by_code(cr, uid, 'account.cash.statement') data.update({ 'journal_id': journal.id, From 1381ac139ed33e858ae6af34f61d04becbcc06bf Mon Sep 17 00:00:00 2001 From: Vo Minh Thu Date: Thu, 29 Sep 2011 15:47:58 +0200 Subject: [PATCH 031/161] [IMP] ir_sequence: (code, company_id) is unique, even for company_id IS NULL. bzr revid: vmt@openerp.com-20110929134758-793vqith9pfcvs7w --- openerp/addons/base/ir/ir_sequence.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/openerp/addons/base/ir/ir_sequence.py b/openerp/addons/base/ir/ir_sequence.py index 3a3a6d4e5e2..56a7da9629b 100644 --- a/openerp/addons/base/ir/ir_sequence.py +++ b/openerp/addons/base/ir/ir_sequence.py @@ -78,6 +78,20 @@ class ir_sequence(openerp.osv.osv.osv): 'padding' : 0, } + def init(self, cr): + # CONSTRAINT/UNIQUE INDEX on (code, company_id) + # /!\ The unique constraint 'unique_name_company_id' is not sufficient, because SQL92 + # only support field names in constraint definitions, and we need a function here: + # we need to special-case company_id to treat all NULL company_id as equal, otherwise + # we would allow duplicate (code, NULL) ir_sequences. + cr.execute(""" + SELECT indexname FROM pg_indexes WHERE indexname = + 'ir_sequence_unique_code_company_id_idx'""") + if not cr.fetchone(): + cr.execute(""" + CREATE UNIQUE INDEX ir_sequence_unique_code_company_id_idx + ON ir_sequence (code, (COALESCE(company_id,-1)))""") + def create(self, cr, uid, values, context=None): values = self._add_missing_default_values(cr, uid, values, context) go = super(ir_sequence, self).create \ @@ -226,8 +240,6 @@ class ir_sequence(openerp.osv.osv.osv): WHERE %s=%%s AND active=true AND (company_id in %%s or company_id is NULL) - ORDER BY company_id, id - LIMIT 1 %s """ % (code_or_id, funw), (sequence_code_or_id, tuple(company_ids))) From d32d0c5637e0b7d85c97278e4479d4e5f8ff1d69 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 29 Sep 2011 15:54:49 +0200 Subject: [PATCH 032/161] [IMP] update py.parse to 0.2 bzr revid: xmo@openerp.com-20110929135449-ssommvnyof6auy29 --- .../web/static/lib/py.parse/.hg_archival.txt | 5 + addons/web/static/lib/py.parse/README | 1 + addons/web/static/lib/py.parse/TODO.rst | 14 +++ addons/web/static/lib/py.parse/lib/py.js | 116 +++++++++++++----- addons/web/static/lib/py.parse/test/test.js | 90 ++++++++++++++ 5 files changed, 196 insertions(+), 30 deletions(-) create mode 100644 addons/web/static/lib/py.parse/.hg_archival.txt create mode 100644 addons/web/static/lib/py.parse/README create mode 100644 addons/web/static/lib/py.parse/TODO.rst create mode 100644 addons/web/static/lib/py.parse/test/test.js diff --git a/addons/web/static/lib/py.parse/.hg_archival.txt b/addons/web/static/lib/py.parse/.hg_archival.txt new file mode 100644 index 00000000000..43d5d80a9e4 --- /dev/null +++ b/addons/web/static/lib/py.parse/.hg_archival.txt @@ -0,0 +1,5 @@ +repo: 076b192d0d8ab2b92d1dbcfa3da055382f30eaea +node: 87fb1b67d6a13f10a1a328104ee4d4b2c36801ec +branch: default +latesttag: 0.2 +latesttagdistance: 1 diff --git a/addons/web/static/lib/py.parse/README b/addons/web/static/lib/py.parse/README new file mode 100644 index 00000000000..453f001ee15 --- /dev/null +++ b/addons/web/static/lib/py.parse/README @@ -0,0 +1 @@ +Parser and evaluator of Python expressions diff --git a/addons/web/static/lib/py.parse/TODO.rst b/addons/web/static/lib/py.parse/TODO.rst new file mode 100644 index 00000000000..3638b681ddc --- /dev/null +++ b/addons/web/static/lib/py.parse/TODO.rst @@ -0,0 +1,14 @@ +* Parser + since parsing expressions, try with a pratt parser + http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ + http://effbot.org/zone/simple-top-down-parsing.htm + +Evaluator +--------- + +* Stop busyworking trivial binary operator +* Make it *trivial* to build Python type-wrappers +* Implement Python's `data model + protocols`_ + for *all* supported operations, optimizations can come later +* Automatically type-wrap everything (for now anyway) diff --git a/addons/web/static/lib/py.parse/lib/py.js b/addons/web/static/lib/py.parse/lib/py.js index d5cf304bb58..0f2415f1252 100644 --- a/addons/web/static/lib/py.parse/lib/py.js +++ b/addons/web/static/lib/py.parse/lib/py.js @@ -5,7 +5,7 @@ var py = {}; NAME = /^[a-zA-Z0-9_]$/; var create = function (o, props) { - function F() {}; + function F() {} F.prototype = o; var inst = new F; for(var name in props) { @@ -13,7 +13,7 @@ var py = {}; inst[name] = props[name]; } return inst; - } + }; var symbols = {}; var comparators = {}; @@ -26,17 +26,17 @@ var py = {}; } else if (this.id === '(end)') { return '(end)'; } else if (this.id === '(comparator)' ) { - var out = ['(comparator', this.expressions[0]]; + var repr = ['(comparator', this.expressions[0]]; for (var i=0;i': return a > b; case '>=': return a >= b; - case 'in': return b.__contains__(a); - case 'not in': return !b.__contains__(a); + case 'in': + if (typeof b === 'string') { + return b.indexOf(a) !== -1; + } + return b.__contains__(a); + case 'not in': + if (typeof b === 'string') { + return b.indexOf(a) === -1; + } + return !b.__contains__(a); } throw new Error('SyntaxError: unknown comparator [[' + operator + ']]'); - } + }; exports.evaluate = function (expr, context) { switch (expr.id) { case '(name)': @@ -444,6 +463,14 @@ var py = {}; case '(string)': case '(number)': return expr.value; + case '(constant)': + if (expr.value === 'None') + return null; + else if (expr.value === 'False') + return false; + else if (expr.value === 'True') + return true; + throw new Error("SyntaxError: unknown constant '" + expr.value + "'"); case '(comparator)': var result, left = exports.evaluate(expr.expressions[0], context); for(var i=0; i= 3')); +assert.ok(py.eval('3 >= 3')); +assert.ok(!py.eval('5 < 3')); +assert.ok(py.eval('1 < 3 < 5')); +assert.ok(py.eval('5 > 3 > 1')); +assert.ok(py.eval('1 < 3 > 2 == 2 > -2 not in (0, 1, 2)')); +// string rich comparisons +assert.ok(py.eval( + 'date >= current', {date: '2010-06-08', current: '2010-06-05'})); + +// Boolean operators +assert.ok(py.eval( + "foo == 'foo' or foo == 'bar'", {foo: 'bar'})); +assert.ok(py.eval( + "foo == 'foo' and bar == 'bar'", {foo: 'foo', bar: 'bar'})); +// - lazyness, second clauses NameError if not short-circuited +assert.ok(py.eval( + "foo == 'foo' or bar == 'bar'", {foo: 'foo'})); +assert.ok(!py.eval( + "foo == 'foo' and bar == 'bar'", {foo: 'bar'})); + +// contains (in) +assert.ok(py.eval( + "foo in ('foo', 'bar')", {foo: 'bar'})); +assert.ok(py.eval('1 in (1, 2, 3, 4)')); +assert.ok(!py.eval('1 in (2, 3, 4)')); +assert.ok(py.eval('type in ("url",)', {type: 'url'})); +assert.ok(!py.eval('type in ("url",)', {type: 'ur'})); +assert.ok(py.eval('1 not in (2, 3, 4)')); +assert.ok(py.eval('type not in ("url",)', {type: 'ur'})); + +assert.ok(py.eval( + "foo in ['foo', 'bar']", {foo: 'bar'})); +// string contains +assert.ok(py.eval('type in "view"', {type: 'view'})); +assert.ok(!py.eval('type in "view"', {type: 'bob'})); +assert.ok(py.eval('type in "url"', {type: 'ur'})); + +// Literals +assert.strictEqual(py.eval('False'), false); +assert.strictEqual(py.eval('True'), true); +assert.strictEqual(py.eval('None'), null); +assert.ok(py.eval('foo == False', {foo: false})); +assert.ok(!py.eval('foo == False', {foo: true})); + +// conversions +assert.strictEqual( + py.eval('bool(date_deadline)', {bool: py.bool, date_deadline: '2008'}), + true); + +// getattr +assert.ok(py.eval('foo.bar', {foo: {bar: true}})); +assert.ok(!py.eval('foo.bar', {foo: {bar: false}})); + +// complex expressions +assert.ok(py.eval( + "state=='pending' and not(date_deadline and (date_deadline < current_date))", + {state: 'pending', date_deadline: false})); +assert.ok(py.eval( + "state=='pending' and not(date_deadline and (date_deadline < current_date))", + {state: 'pending', date_deadline: '2010-05-08', current_date: '2010-05-08'}));; From 8dbbacca082f0f2c3355971527c2addd677cecae Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Thu, 29 Sep 2011 16:15:56 +0200 Subject: [PATCH 033/161] [imp] improved logging, now blacklist openerplib bzr revid: nicolas.vanhoren@openerp.com-20110929141556-j92hlk7j2ahx8i70 --- .bzrignore | 1 - logging.json | 27 +++++++++++++++++++++++++++ openerp-web.py | 12 ++++++++---- 3 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 logging.json diff --git a/.bzrignore b/.bzrignore index 7ae985ce4df..b83a43bf1d4 100644 --- a/.bzrignore +++ b/.bzrignore @@ -9,4 +9,3 @@ RE:^include/ RE:^share/ RE:^man/ RE:^lib/ -logging.cfg diff --git a/logging.json b/logging.json new file mode 100644 index 00000000000..36b2952a6ec --- /dev/null +++ b/logging.json @@ -0,0 +1,27 @@ +{ + "version": 1, + "formatters": { + "simple": { + "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + } + }, + "handlers": { + "console": { + "class": "logging.StreamHandler", + "level": "DEBUG", + "formatter": "simple", + "stream": "ext://sys.stdout" + } + }, + "loggers": { + "web": { + }, + "web.common.openerplib": { + "level": "INFO" + } + }, + "root": { + "level": "DEBUG", + "handlers": ["console"] + } +} diff --git a/openerp-web.py b/openerp-web.py index 928a62e4528..e167568cdab 100755 --- a/openerp-web.py +++ b/openerp-web.py @@ -2,6 +2,7 @@ import optparse import os import sys +import json import tempfile import logging import logging.config @@ -48,7 +49,7 @@ logging_opts = optparse.OptionGroup(optparser, "Logging") logging_opts.add_option("--log-level", dest="log_level", type="choice", default='debug', help="Global logging level", metavar="LOG_LEVEL", choices=['debug', 'info', 'warning', 'error', 'critical']) -logging_opts.add_option("--log-config", dest="log_config", +logging_opts.add_option("--log-config", dest="log_config", default=os.path.join(os.path.dirname(__file__), "logging.json"), help="Logging configuration file", metavar="FILE") optparser.add_option_group(logging_opts) @@ -60,10 +61,13 @@ if __name__ == "__main__": os.environ["TZ"] = "UTC" - if not options.log_config: - logging.basicConfig(level=getattr(logging, options.log_level.upper())) + if sys.version_info >= (2, 7): + with open(options.log_config) as file: + dct = json.load(file) + logging.config.dictConfig(dct) + logging.getLogger("").setLevel(getattr(logging, options.log_level.upper())) else: - logging.config.fileConfig(options.log_config) + logging.basicConfig(level=getattr(logging, options.log_level.upper())) app = web.common.dispatch.Root(options) From d793d6c1aeddc4c7f79d22cc7f1c8a12533e70e6 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 29 Sep 2011 16:24:10 +0200 Subject: [PATCH 034/161] [ADD] atom context keys (uid and current_date) to evaluation context of row colors bzr revid: xmo@openerp.com-20110929142410-1f9btd6f3ws0srpj --- addons/web/static/src/js/view_list.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index cb8637ff0a4..144e0309c16 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -142,11 +142,16 @@ openerp.web.ListView = openerp.web.View.extend( /** @lends openerp.web.ListView# */ color_for: function (record) { if (!this.colors) { return ''; } + var context = _.extend({}, record.attributes, { + uid: this.session.uid, + current_date: new Date().toString('yyyy-MM-dd') + // TODO: time, datetime, relativedelta + }); for(var i=0, len=this.colors.length; i Date: Thu, 29 Sep 2011 16:29:19 +0200 Subject: [PATCH 035/161] [imp] changed logging to be like server bzr revid: nicolas.vanhoren@openerp.com-20110929142919-v8pzr4zpy984e5qc --- logging.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logging.json b/logging.json index 36b2952a6ec..1f982a6d4d0 100644 --- a/logging.json +++ b/logging.json @@ -2,7 +2,7 @@ "version": 1, "formatters": { "simple": { - "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + "format": "[%(asctime)s] %(levelname)s:%(name)s:%(message)s" } }, "handlers": { From ba86faac47ac3489e6db87265a4bd0ca6e576ca6 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 29 Sep 2011 16:50:31 +0200 Subject: [PATCH 036/161] [IMP] shave ~190ms off of *big* listview rendering speed make conversion of internal Records to form-shape faster by iterating over the attributes object directly instead of using _.each bzr revid: xmo@openerp.com-20110929145031-q7mqf43gza94ekj6 --- addons/web/static/src/js/view_list.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/web/static/src/js/view_list.js b/addons/web/static/src/js/view_list.js index 144e0309c16..12711e8b2fe 100644 --- a/addons/web/static/src/js/view_list.js +++ b/addons/web/static/src/js/view_list.js @@ -1391,10 +1391,10 @@ var Record = openerp.web.Class.extend(/** @lends Record# */{ * @returns {Object} record displayable in a form view */ toForm: function () { - var form_data = {}; - _(this.attributes).each(function (value, key) { - form_data[key] = {value: value}; - }); + var form_data = {}, attrs = this.attributes; + for(var k in attrs) { + form_data[k] = {value: attrs[k]}; + } return {data: form_data}; } From 5c2d8e4cdc9a92187891a8476de28dcc8ae4b6f5 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Thu, 29 Sep 2011 16:57:51 +0200 Subject: [PATCH 037/161] [fix] problem in database when creating a new database bzr revid: nicolas.vanhoren@openerp.com-20110929145751-4oh0b9uqll8wx3zj --- addons/web/static/src/js/chrome.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/addons/web/static/src/js/chrome.js b/addons/web/static/src/js/chrome.js index e6a850cd799..1955298ba27 100644 --- a/addons/web/static/src/js/chrome.js +++ b/addons/web/static/src/js/chrome.js @@ -1,7 +1,6 @@ /*--------------------------------------------------------- * OpenERP Web chrome *---------------------------------------------------------*/ - openerp.web.chrome = function(openerp) { var QWeb = openerp.web.qweb; @@ -300,9 +299,9 @@ openerp.web.Database = openerp.web.Widget.extend(/** @lends openerp.web.Database var admin = result[1][0]; setTimeout(function () { - self.stop(); self.widget_parent.do_login( info.db, admin.login, admin.password); + self.stop(); $.unblockUI(); }); }); From 58ece9f856f2d8e0ae1495b780afec5fd354e52a Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Thu, 29 Sep 2011 17:13:22 +0200 Subject: [PATCH 038/161] [fix] error message when login invalid broken bzr revid: nicolas.vanhoren@openerp.com-20110929151322-zcymbsemo962ky0j --- addons/web/static/src/css/base.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/web/static/src/css/base.css b/addons/web/static/src/css/base.css index c75fe786543..8c99823434c 100644 --- a/addons/web/static/src/css/base.css +++ b/addons/web/static/src/css/base.css @@ -125,7 +125,7 @@ body.openerp, .openerp textarea, .openerp input, .openerp select, .openerp optio margin-top: 5px; text-align: center; } -.openerp .login.login_invalid .login_error_message { +.openerp .login .login_invalid .login_error_message { display: block; } From eb92957c8c25b2c8a092fa996970aba795a8c0fd Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Thu, 29 Sep 2011 17:40:07 +0200 Subject: [PATCH 039/161] [fix] obvious bug, field used in a on_change but not declared in the view bzr revid: nicolas.vanhoren@openerp.com-20110929154007-gtxf31frsuukepvf --- addons/account_voucher/voucher_payment_receipt_view.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/addons/account_voucher/voucher_payment_receipt_view.xml b/addons/account_voucher/voucher_payment_receipt_view.xml index 6a9e69ab27e..9c8bdffb35d 100644 --- a/addons/account_voucher/voucher_payment_receipt_view.xml +++ b/addons/account_voucher/voucher_payment_receipt_view.xml @@ -280,6 +280,7 @@
+ Date: Fri, 30 Sep 2011 00:23:47 +0200 Subject: [PATCH 040/161] [IMP] audittrail cleanup and speedup - test for auditrail before anything else - dont allocate a different cursor bzr revid: al@openerp.com-20110929222347-c2ywh8nwhl27d9uv --- addons/audittrail/audittrail.py | 154 +++++++------------------------- 1 file changed, 34 insertions(+), 120 deletions(-) diff --git a/addons/audittrail/audittrail.py b/addons/audittrail/audittrail.py index 4eded2f299d..80af2e7ea3a 100644 --- a/addons/audittrail/audittrail.py +++ b/addons/audittrail/audittrail.py @@ -123,9 +123,6 @@ class audittrail_rule(osv.osv): #End Loop return True -audittrail_rule() - - class audittrail_log(osv.osv): """ For Audittrail Log @@ -161,9 +158,6 @@ class audittrail_log(osv.osv): } _order = "timestamp desc" -audittrail_log() - - class audittrail_log_line(osv.osv): """ Audittrail Log Line. @@ -181,9 +175,6 @@ class audittrail_log_line(osv.osv): 'field_description': fields.char('Field Description', size=64), } -audittrail_log_line() - - class audittrail_objects_proxy(object_proxy): """ Uses Object proxy for auditing changes on object of subscribed Rules""" @@ -289,8 +280,7 @@ class audittrail_objects_proxy(object_proxy): #End Loop return True - - def log_fct(self, db, uid, model, method, fct_src, *args): + def log_fct(self, cr, uid, model, method, fct_src, *args): """ Logging function: This function is performs logging oprations according to method @param db: the current database @@ -304,8 +294,7 @@ class audittrail_objects_proxy(object_proxy): uid_orig = uid uid = 1 res2 = args - pool = pooler.get_pool(db) - cr = pooler.get_db(db).cursor() + pool = pooler.get_pool(cr.dbname) resource_pool = pool.get(model) log_pool = pool.get('audittrail.log') model_pool = pool.get('ir.model') @@ -316,8 +305,7 @@ class audittrail_objects_proxy(object_proxy): model = model_pool.browse(cr, uid, model_id) if method in ('create'): - res_id = fct_src(db, uid_orig, model.model, method, *args) - cr.commit() + res_id = fct_src(cr, uid_orig, model.model, method, *args) resource = resource_pool.read(cr, uid, res_id, args[0].keys()) vals = { "method": method, @@ -338,14 +326,12 @@ class audittrail_objects_proxy(object_proxy): lines.append(line) self.create_log_line(cr, uid, log_id, model, lines) - cr.commit() - cr.close() return res_id elif method in ('read'): res_ids = args[0] old_values = {} - res = fct_src(db, uid_orig, model.model, method, *args) + res = fct_src(cr, uid_orig, model.model, method, *args) if type(res) == list: for v in res: old_values[v['id']] = v @@ -370,8 +356,6 @@ class audittrail_objects_proxy(object_proxy): lines.append(line) self.create_log_line(cr, uid, log_id, model, lines) - cr.commit() - cr.close() return res elif method in ('unlink'): @@ -401,9 +385,7 @@ class audittrail_objects_proxy(object_proxy): lines.append(line) self.create_log_line(cr, uid, log_id, model, lines) - res = fct_src(db, uid_orig, model.model, method, *args) - cr.commit() - cr.close() + res = fct_src(cr, uid_orig, model.model, method, *args) return res else: res_ids = [] @@ -428,8 +410,7 @@ class audittrail_objects_proxy(object_proxy): old_values_text[field] = self.get_value_text(cr, uid, field, resource[field], model) old_values[resource_id] = {'text':old_values_text, 'value': old_value} - res = fct_src(db, uid_orig, model.model, method, *args) - cr.commit() + res = fct_src(cr, uid_orig, model.model, method, *args) if res_ids: for resource in resource_pool.read(cr, uid, res_ids): @@ -457,107 +438,40 @@ class audittrail_objects_proxy(object_proxy): lines.append(line) self.create_log_line(cr, uid, log_id, model, lines) - cr.commit() - cr.close() return res return True - - - def execute(self, db, uid, model, method, *args, **kw): - """ - Overrides Object Proxy execute method - @param db: the current database - @param uid: the current user's ID for security checks, - @param object: Object who's values are being changed - @param method: get any method and create log - - @return: Returns result as per method of Object proxy - """ - uid_orig = uid - uid = 1 - pool = pooler.get_pool(db) - model_pool = pool.get('ir.model') - rule_pool = pool.get('audittrail.rule') - cr = pooler.get_db(db).cursor() - cr.autocommit(True) - logged_uids = [] - fct_src = super(audittrail_objects_proxy, self).execute - - def my_fct(db, uid, model, method, *args): - rule = False - model_ids = model_pool.search(cr, uid, [('model', '=', model)]) + def check_rules(self, cr, uid, model, method): + pool = pooler.get_pool(cr.dbname) + # Check if auditrails is installed for that db and then if one rule match + if 'audittrail.rule' in pool.models: + model_ids = pool.get('ir.model').search(cr, 1, [('model', '=', model)]) model_id = model_ids and model_ids[0] or False + if model_id: + rule_ids = pool.get('audittrail.rule').search(cr, 1, [('object_id', '=', model_id), ('state', '=', 'subscribed')]) + for rule in pool.get('audittrail.rule').read(cr, 1, rule_ids, ['user_id','log_read','log_write','log_create','log_unlink','log_action','log_workflow']): + if len(rule['user_id'])==0 or uid in rule['user_id']: + if rule.get('log_'+method,0): + return True + elif method not in ('default_get','read','fields_view_get','fields_get','search','search_count','name_search','name_get','get','request_get', 'get_sc', 'unlink', 'write', 'create'): + if rule['log_action']: + return True - for model_name in pool.obj_list(): - if model_name == 'audittrail.rule': - rule = True - if not rule: - return fct_src(db, uid_orig, model, method, *args) - if not model_id: - return fct_src(db, uid_orig, model, method, *args) + def execute_cr(self, cr, uid, model, method, *args, **kw): + fct_src = super(audittrail_objects_proxy, self).execute_cr + if self.check_rules(cr,uid,model,method): + res = self.log_fct(cr, uid, model, method, fct_src, *args) + else: + res = fct_src(cr, uid, model, method, *args) + return res - rule_ids = rule_pool.search(cr, uid, [('object_id', '=', model_id), ('state', '=', 'subscribed')]) - if not rule_ids: - return fct_src(db, uid_orig, model, method, *args) - - for thisrule in rule_pool.browse(cr, uid, rule_ids): - for user in thisrule.user_id: - logged_uids.append(user.id) - if not logged_uids or uid in logged_uids: - if method in ('read', 'write', 'create', 'unlink'): - if getattr(thisrule, 'log_' + method): - return self.log_fct(db, uid_orig, model, method, fct_src, *args) - - elif method not in ('default_get','read','fields_view_get','fields_get','search','search_count','name_search','name_get','get','request_get', 'get_sc', 'unlink', 'write', 'create'): - if thisrule.log_action: - return self.log_fct(db, uid_orig, model, method, fct_src, *args) - - return fct_src(db, uid_orig, model, method, *args) - try: - res = my_fct(db, uid, model, method, *args) - return res - finally: - cr.close() - - def exec_workflow(self, db, uid, model, method, *args, **argv): - uid_orig = uid - uid = 1 - - pool = pooler.get_pool(db) - logged_uids = [] - fct_src = super(audittrail_objects_proxy, self).exec_workflow - field = method - rule = False - model_pool = pool.get('ir.model') - rule_pool = pool.get('audittrail.rule') - cr = pooler.get_db(db).cursor() - cr.autocommit(True) - try: - model_ids = model_pool.search(cr, uid, [('model', '=', model)]) - for obj_name in pool.obj_list(): - if obj_name == 'audittrail.rule': - rule = True - if not rule: - return super(audittrail_objects_proxy, self).exec_workflow(db, uid_orig, model, method, *args, **argv) - if not model_ids: - return super(audittrail_objects_proxy, self).exec_workflow(db, uid_orig, model, method, *args, **argv) - - rule_ids = rule_pool.search(cr, uid, [('object_id', 'in', model_ids), ('state', '=', 'subscribed')]) - if not rule_ids: - return super(audittrail_objects_proxy, self).exec_workflow(db, uid_orig, model, method, *args, **argv) - - for thisrule in rule_pool.browse(cr, uid, rule_ids): - for user in thisrule.user_id: - logged_uids.append(user.id) - if not logged_uids or uid in logged_uids: - if thisrule.log_workflow: - return self.log_fct(db, uid_orig, model, method, fct_src, *args) - return super(audittrail_objects_proxy, self).exec_workflow(db, uid_orig, model, method, *args, **argv) - - return True - finally: - cr.close() + def exec_workflow_cr(self, cr, uid, model, method, *args, **argv): + fct_src = super(audittrail_objects_proxy, self).exec_workflow_cr + if self.check_rules(cr,uid,model,'workflow'): + res = self.log_fct(cr, uid, model, method, fct_src, *args) + else: + res = fct_src(cr, uid, model, method, *args) + return res audittrail_objects_proxy() From 46d3f7e42c915d10349b1118ce1e648330bcf8c6 Mon Sep 17 00:00:00 2001 From: Antony Lesuisse Date: Fri, 30 Sep 2011 00:49:19 +0200 Subject: [PATCH 041/161] [FIX] osv object_proxy to use new style class bzr revid: al@openerp.com-20110929224919-uacfp8w53jfqikkj --- openerp/osv/osv.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/osv/osv.py b/openerp/osv/osv.py index 821c52a55ef..0e27e71d475 100644 --- a/openerp/osv/osv.py +++ b/openerp/osv/osv.py @@ -39,7 +39,7 @@ except_osv = openerp.exceptions.Warning service = None -class object_proxy(): +class object_proxy(object): def __init__(self): self.logger = logging.getLogger('web-services') global service From 8507f7cc4a446da13a83abf5ff711a730bc60e8c Mon Sep 17 00:00:00 2001 From: Launchpad Translations on behalf of openerp <> Date: Fri, 30 Sep 2011 04:40:48 +0000 Subject: [PATCH 042/161] Launchpad automatic translations update. bzr revid: launchpad_translations_on_behalf_of_openerp-20110930043724-cv7w2vcqt7soa9gc bzr revid: launchpad_translations_on_behalf_of_openerp-20110930044048-j5gv3hmo9cj3dhyg --- addons/account/i18n/et.po | 200 ++++++++++++++++-------------- openerp/addons/base/i18n/zh_TW.po | 8 +- 2 files changed, 108 insertions(+), 100 deletions(-) diff --git a/addons/account/i18n/et.po b/addons/account/i18n/et.po index 6c6a6385ec9..b671a24e720 100644 --- a/addons/account/i18n/et.po +++ b/addons/account/i18n/et.po @@ -7,24 +7,24 @@ msgstr "" "Project-Id-Version: OpenERP Server 6.0dev\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2011-01-11 11:14+0000\n" -"PO-Revision-Date: 2010-12-12 00:12+0000\n" -"Last-Translator: qdp (OpenERP) \n" +"PO-Revision-Date: 2011-09-28 14:57+0000\n" +"Last-Translator: Raiko Pajur \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-09-17 04:56+0000\n" -"X-Generator: Launchpad (build 13955)\n" +"X-Launchpad-Export-Date: 2011-09-30 04:40+0000\n" +"X-Generator: Launchpad (build 14071)\n" #. module: account #: model:process.transition,name:account.process_transition_supplierreconcilepaid0 msgid "System payment" -msgstr "" +msgstr "Süsteemi maksed" #. module: account #: view:account.journal:0 msgid "Other Configuration" -msgstr "" +msgstr "Muud konfiguratsioonid" #. module: account #: code:addons/account/wizard/account_open_closed_fiscalyear.py:40 @@ -39,6 +39,8 @@ msgid "" "You cannot remove/deactivate an account which is set as a property to any " "Partner." msgstr "" +"Sa ei saa kustutada / desaktiveerida kontot, mis on määratud mis tahes " +"\"Partner\" varaks." #. module: account #: view:account.move.reconcile:0 @@ -48,7 +50,7 @@ msgstr "" #. module: account #: field:account.installer.modules,account_voucher:0 msgid "Voucher Management" -msgstr "" +msgstr "Voucheri juhtimine" #. module: account #: view:account.account:0 @@ -133,13 +135,13 @@ msgstr "Raamatupidamise kirjed-" #: code:addons/account/account.py:1291 #, python-format msgid "You can not delete posted movement: \"%s\"!" -msgstr "" +msgstr "Sa ei saa kustutada postitatud liikumist: \"%s\"!" #. module: account #: report:account.invoice:0 #: field:account.invoice.line,origin:0 msgid "Origin" -msgstr "Päritolu" +msgstr "Allikas" #. module: account #: view:account.account:0 @@ -164,7 +166,7 @@ msgstr "Viide" #. module: account #: view:account.open.closed.fiscalyear:0 msgid "Choose Fiscal Year " -msgstr "" +msgstr "Vali eelarveaasta " #. module: account #: help:account.payment.term,active:0 @@ -172,12 +174,14 @@ msgid "" "If the active field is set to False, it will allow you to hide the payment " "term without removing it." msgstr "" +"Kui aktiivne ala on väärne ( False ), siis see võimaldab teil peita/varjata " +"maksetähtaeg seda kustutamata." #. module: account #: code:addons/account/invoice.py:1421 #, python-format msgid "Warning!" -msgstr "" +msgstr "Hoiatus!" #. module: account #: field:account.fiscal.position.account,account_src_id:0 @@ -204,7 +208,7 @@ msgstr "Negatiivne" #: code:addons/account/wizard/account_move_journal.py:95 #, python-format msgid "Journal: %s" -msgstr "" +msgstr "Päevik: %s" #. module: account #: help:account.analytic.journal,type:0 @@ -231,7 +235,7 @@ msgstr "konto.maks" msgid "" "No period defined for this date: %s !\n" "Please create a fiscal year." -msgstr "" +msgstr "Periood ei ole defineeritud sellele kuupäevale: %s" #. module: account #: model:ir.model,name:account.model_account_move_line_reconcile_select @@ -259,7 +263,7 @@ msgstr "" #: code:addons/account/invoice.py:1210 #, python-format msgid "Invoice '%s' is paid partially: %s%s of %s%s (%s%s remaining)" -msgstr "" +msgstr "Arve '%s' on makstud osaliselt: %s%s on tasutud %s%s (%s%s maksmata)" #. module: account #: model:process.transition,note:account.process_transition_supplierentriesreconcile0 @@ -280,7 +284,7 @@ msgstr "Teie ei saa lisada/muuta suletud päeviku kirjeid." #. module: account #: view:account.bank.statement:0 msgid "Calculated Balance" -msgstr "" +msgstr "Välja arvutatud tasakaal (Calculated Balance)" #. module: account #: model:ir.actions.act_window,name:account.action_account_use_model_create_entry @@ -352,7 +356,7 @@ msgstr "Ostu omadused" #: view:account.installer:0 #: view:account.installer.modules:0 msgid "Configure" -msgstr "" +msgstr "Seadista" #. module: account #: selection:account.entries.report,month:0 @@ -361,7 +365,7 @@ msgstr "" #: selection:report.account.sales,month:0 #: selection:report.account_type.sales,month:0 msgid "June" -msgstr "" +msgstr "Juuni" #. module: account #: model:ir.actions.act_window,help:account.action_account_moves_bank @@ -395,12 +399,12 @@ msgstr "" #. module: account #: selection:account.journal,type:0 msgid "Opening/Closing Situation" -msgstr "" +msgstr "Avamise/Sulgemise situatsioon" #. module: account #: help:account.journal,currency:0 msgid "The currency used to enter statement" -msgstr "" +msgstr "Valuuta väite sisestamiseks" #. module: account #: field:account.open.closed.fiscalyear,fyear_id:0 @@ -498,17 +502,17 @@ msgstr "Päevik" #. module: account #: model:ir.model,name:account.model_account_invoice_confirm msgid "Confirm the selected invoices" -msgstr "" +msgstr "Kinnita valitud arved" #. module: account #: field:account.addtmpl.wizard,cparent_id:0 msgid "Parent target" -msgstr "" +msgstr "Lapsevanema sihtmärk" #. module: account #: field:account.bank.statement,account_id:0 msgid "Account used in this journal" -msgstr "" +msgstr "Konto kasutatud selles arveraamatus" #. module: account #: help:account.aged.trial.balance,chart_account_id:0 @@ -527,7 +531,7 @@ msgstr "" #: help:account.report.general.ledger,chart_account_id:0 #: help:account.vat.declaration,chart_account_id:0 msgid "Select Charts of Accounts" -msgstr "" +msgstr "Vali Kontode graafikud" #. module: account #: view:product.product:0 @@ -537,7 +541,7 @@ msgstr "Ostumaksud" #. module: account #: model:ir.model,name:account.model_account_invoice_refund msgid "Invoice Refund" -msgstr "" +msgstr "Arveraamatu tagasimakse" #. module: account #: report:account.overdue:0 @@ -560,7 +564,7 @@ msgstr "" #: field:account.fiscal.position,tax_ids:0 #: field:account.fiscal.position.template,tax_ids:0 msgid "Tax Mapping" -msgstr "" +msgstr "Maksude kaardistamine" #. module: account #: model:ir.actions.act_window,name:account.action_account_fiscalyear_close_state @@ -571,7 +575,7 @@ msgstr "Sule majandusaasta" #. module: account #: model:process.transition,note:account.process_transition_confirmstatementfromdraft0 msgid "The accountant confirms the statement." -msgstr "" +msgstr "Raamatupidaja kinnitab selle avalduse" #. module: account #: selection:account.balance.report,display_account:0 @@ -587,12 +591,12 @@ msgstr "Kõik" #. module: account #: field:account.invoice.report,address_invoice_id:0 msgid "Invoice Address Name" -msgstr "" +msgstr "Arveraamatu Aadressi Nimi" #. module: account #: selection:account.installer,period:0 msgid "3 Monthly" -msgstr "" +msgstr "Iga 3 kuu tagant" #. module: account #: view:account.unreconcile.reconcile:0 @@ -604,7 +608,7 @@ msgstr "" #. module: account #: view:analytic.entries.report:0 msgid " 30 Days " -msgstr "" +msgstr " 30 päeva " #. module: account #: field:ir.sequence,fiscal_ids:0 @@ -624,7 +628,7 @@ msgstr "" #. module: account #: sql_constraint:account.sequence.fiscalyear:0 msgid "Main Sequence must be different from current !" -msgstr "" +msgstr "Pea" #. module: account #: field:account.invoice.tax,tax_amount:0 @@ -652,12 +656,12 @@ msgstr "Sulge periood" #. module: account #: model:ir.model,name:account.model_account_common_partner_report msgid "Account Common Partner Report" -msgstr "" +msgstr "Konto tava \"Partner\" aruanne" #. module: account #: field:account.fiscalyear.close,period_id:0 msgid "Opening Entries Period" -msgstr "" +msgstr "Avatud sissekanete periood" #. module: account #: model:ir.model,name:account.model_account_journal_period @@ -791,7 +795,7 @@ msgstr "J.C./liiguta nime" #: selection:report.account.sales,month:0 #: selection:report.account_type.sales,month:0 msgid "September" -msgstr "" +msgstr "September" #. module: account #: selection:account.subscription,period_type:0 @@ -802,7 +806,7 @@ msgstr "päevad" #: help:account.account.template,nocreate:0 msgid "" "If checked, the new chart of accounts will not contain this by default." -msgstr "" +msgstr "Kui märgitud, siis uus kontode graafik ei sisalda seda puudujääki." #. module: account #: code:addons/account/wizard/account_invoice_refund.py:102 @@ -825,7 +829,7 @@ msgstr "Arvutus" #. module: account #: view:account.move.line:0 msgid "Next Partner to reconcile" -msgstr "" +msgstr "Kooskõlastama järgmise \"Partner\"-iga" #. module: account #: code:addons/account/account_move_line.py:1191 @@ -834,12 +838,14 @@ msgid "" "You can not do this modification on a confirmed entry ! Please note that you " "can just change some non important fields !" msgstr "" +"Teie ei saa teha see muudatus kinnitatud kirjel ! Teie saate muuta ainult " +"mõned vähetähtsad väljad !" #. module: account #: view:account.invoice.report:0 #: field:account.invoice.report,delay_to_pay:0 msgid "Avg. Delay To Pay" -msgstr "" +msgstr "Keskmine viivitus maksete tegemisel" #. module: account #: model:ir.actions.act_window,name:account.action_account_tax_chart @@ -862,7 +868,7 @@ msgstr "Tähtaeg" #: view:account.invoice.report:0 #: field:account.invoice.report,price_total_tax:0 msgid "Total With Tax" -msgstr "" +msgstr "Kokku koos maksudega" #. module: account #: view:account.invoice:0 @@ -870,7 +876,7 @@ msgstr "" #: view:validate.account.move:0 #: view:validate.account.move.lines:0 msgid "Approve" -msgstr "" +msgstr "Nõustu" #. module: account #: view:account.invoice:0 @@ -925,7 +931,7 @@ msgstr "" #. module: account #: view:account.analytic.line:0 msgid "Purchases" -msgstr "" +msgstr "Ostud" #. module: account #: field:account.model,lines_id:0 @@ -972,7 +978,7 @@ msgstr "Partneri bilanss" #. module: account #: field:account.bank.accounts.wizard,acc_name:0 msgid "Account Name." -msgstr "" +msgstr "Konto nimi." #. module: account #: field:account.chart.template,property_reserve_and_surplus_account:0 @@ -983,7 +989,7 @@ msgstr "" #. module: account #: field:report.account.receivable,name:0 msgid "Week of Year" -msgstr "" +msgstr "Nädal" #. module: account #: field:account.bs.report,display_type:0 @@ -995,12 +1001,12 @@ msgstr "Rõhtpaigutus" #. module: account #: view:board.board:0 msgid "Customer Invoices to Approve" -msgstr "" +msgstr "Kliendi arved kinnitamiseks" #. module: account #: help:account.fiscalyear.close,fy_id:0 msgid "Select a Fiscal year to close" -msgstr "" +msgstr "Vali eelarve aasta mida sulgeda" #. module: account #: help:account.account,user_type:0 @@ -1018,13 +1024,13 @@ msgstr "" #. module: account #: report:account.partner.balance:0 msgid "In dispute" -msgstr "" +msgstr "Vaidlustatav" #. module: account #: model:ir.actions.act_window,name:account.action_view_bank_statement_tree #: model:ir.ui.menu,name:account.journal_cash_move_lines msgid "Cash Registers" -msgstr "" +msgstr "Raha register" #. module: account #: selection:account.account.type,report_type:0 @@ -1042,7 +1048,7 @@ msgstr "-" #. module: account #: view:account.analytic.account:0 msgid "Manager" -msgstr "" +msgstr "Juhataja" #. module: account #: view:account.subscription.generate:0 @@ -1052,7 +1058,7 @@ msgstr "" #. module: account #: selection:account.bank.accounts.wizard,account_type:0 msgid "Bank" -msgstr "" +msgstr "Pank" #. module: account #: field:account.period,date_start:0 @@ -1062,13 +1068,13 @@ msgstr "Perioodi algus" #. module: account #: model:process.transition,name:account.process_transition_confirmstatementfromdraft0 msgid "Confirm statement" -msgstr "" +msgstr "Kinnita avaldus" #. module: account #: field:account.fiscal.position.tax,tax_dest_id:0 #: field:account.fiscal.position.tax.template,tax_dest_id:0 msgid "Replacement Tax" -msgstr "" +msgstr "Vahetus maks" #. module: account #: selection:account.move.line,centralisation:0 @@ -1087,12 +1093,12 @@ msgstr "" #. module: account #: view:account.invoice.cancel:0 msgid "Cancel Invoices" -msgstr "" +msgstr "Peata arved" #. module: account #: view:account.unreconcile.reconcile:0 msgid "Unreconciliation transactions" -msgstr "" +msgstr "Mittesobivad tehingud" #. module: account #: field:account.invoice.tax,tax_code_id:0 @@ -1110,7 +1116,7 @@ msgstr "" #. module: account #: help:account.move.line,move_id:0 msgid "The move of this entry line." -msgstr "" +msgstr "Selle rea liigutus." #. module: account #: field:account.move.line.reconcile,trans_nbr:0 @@ -1174,7 +1180,7 @@ msgstr "Konto" #. module: account #: field:account.tax,include_base_amount:0 msgid "Included in base amount" -msgstr "" +msgstr "Lisa baas osa" #. module: account #: view:account.entries.report:0 @@ -1186,7 +1192,7 @@ msgstr "" #. module: account #: field:account.account,level:0 msgid "Level" -msgstr "" +msgstr "Tase" #. module: account #: report:account.invoice:0 @@ -1207,7 +1213,7 @@ msgstr "Maksud" #: code:addons/account/wizard/account_report_common.py:120 #, python-format msgid "Select a starting and an ending period" -msgstr "" +msgstr "Vali algus ja lõpp periood" #. module: account #: model:ir.model,name:account.model_account_account_template @@ -1217,12 +1223,12 @@ msgstr "Mallid kontodele" #. module: account #: view:account.tax.code.template:0 msgid "Search tax template" -msgstr "" +msgstr "Otsi maksu templati" #. module: account #: report:account.invoice:0 msgid "Your Reference" -msgstr "" +msgstr "Teie viide" #. module: account #: view:account.move.reconcile:0 @@ -1246,7 +1252,7 @@ msgstr "" #. module: account #: view:account.invoice:0 msgid "Reset to Draft" -msgstr "" +msgstr "Lähtesta mustandiks" #. module: account #: view:wizard.multi.charts.accounts:0 @@ -1268,7 +1274,7 @@ msgstr "" #: model:ir.actions.act_window,name:account.action_partner_all #: model:ir.ui.menu,name:account.next_id_22 msgid "Partners" -msgstr "" +msgstr "Partnerid" #. module: account #: view:account.bank.statement:0 @@ -1323,7 +1329,7 @@ msgstr "Bilanss pole 0" #. module: account #: view:account.tax:0 msgid "Search Taxes" -msgstr "" +msgstr "Otsi maksu" #. module: account #: model:ir.model,name:account.model_account_analytic_cost_ledger @@ -1338,7 +1344,7 @@ msgstr "Loo sissekanded" #. module: account #: field:account.entries.report,nbr:0 msgid "# of Items" -msgstr "" +msgstr "# detaile" #. module: account #: field:account.automatic.reconcile,max_amount:0 @@ -1353,7 +1359,7 @@ msgstr "Arvuta maksud" #. module: account #: field:wizard.multi.charts.accounts,code_digits:0 msgid "# of Digits" -msgstr "" +msgstr "# numbrit" #. module: account #: field:account.journal,entry_posted:0 @@ -1364,7 +1370,7 @@ msgstr "" #: view:account.invoice.report:0 #: field:account.invoice.report,price_total:0 msgid "Total Without Tax" -msgstr "" +msgstr "Kokku ilma maksudeta" #. module: account #: model:ir.actions.act_window,help:account.action_move_journal_line @@ -1378,7 +1384,7 @@ msgstr "" #. module: account #: view:account.entries.report:0 msgid "# of Entries " -msgstr "" +msgstr "# sisestusi " #. module: account #: model:ir.model,name:account.model_temp_range @@ -1435,7 +1441,7 @@ msgstr "Mall finantspositsioonile" #. module: account #: model:account.tax.code,name:account.account_tax_code_0 msgid "Tax Code Test" -msgstr "" +msgstr "Maksu koodi test" #. module: account #: field:account.automatic.reconcile,reconciled:0 @@ -1445,22 +1451,22 @@ msgstr "" #. module: account #: field:account.journal.view,columns_id:0 msgid "Columns" -msgstr "" +msgstr "Veerud" #. module: account #: report:account.overdue:0 msgid "." -msgstr "" +msgstr "." #. module: account #: view:account.analytic.cost.ledger.journal.report:0 msgid "and Journals" -msgstr "" +msgstr "ja arveraamatud" #. module: account #: field:account.journal,groups_id:0 msgid "Groups" -msgstr "" +msgstr "Grupid" #. module: account #: field:account.invoice,amount_untaxed:0 @@ -1471,18 +1477,20 @@ msgstr "Maksuvaba" #. module: account #: view:account.partner.reconcile.process:0 msgid "Go to next partner" -msgstr "" +msgstr "Mine järgmise \"Partner\"-ile" #. module: account #: view:account.bank.statement:0 msgid "Search Bank Statements" -msgstr "" +msgstr "Otsi panga avaldust" #. module: account #: sql_constraint:account.model.line:0 msgid "" "Wrong credit or debit value in model (Credit + Debit Must Be greater \"0\")!" msgstr "" +"Vale krediidi või deebeti arv mudelis ( Krediit + Deebet Peab olema suurem " +"kui \"0\" ) !" #. module: account #: view:account.chart.template:0 @@ -1516,14 +1524,14 @@ msgstr "" #. module: account #: report:account.analytic.account.cost_ledger:0 msgid "Date/Code" -msgstr "" +msgstr "Kuupäev/Kood" #. module: account #: field:account.analytic.line,general_account_id:0 #: view:analytic.entries.report:0 #: field:analytic.entries.report,general_account_id:0 msgid "General Account" -msgstr "" +msgstr "Üldine konto" #. module: account #: field:res.partner,debit_limit:0 @@ -1554,13 +1562,13 @@ msgstr "" #. module: account #: field:wizard.multi.charts.accounts,seq_journal:0 msgid "Separated Journal Sequences" -msgstr "" +msgstr "Eraldatud päeviku järjekorrad" #. module: account #: field:account.bank.statement,user_id:0 #: view:account.invoice:0 msgid "Responsible" -msgstr "" +msgstr "Vastutav" #. module: account #: report:account.overdue:0 @@ -1570,7 +1578,7 @@ msgstr "Vahesumma:" #. module: account #: model:ir.actions.act_window,name:account.action_report_account_type_sales_tree_all msgid "Sales by Account Type" -msgstr "" +msgstr "Müügid konto järgi" #. module: account #: view:account.invoice.refund:0 @@ -1582,7 +1590,7 @@ msgstr "" #. module: account #: model:ir.ui.menu,name:account.periodical_processing_invoicing msgid "Invoicing" -msgstr "" +msgstr "Arveldamine" #. module: account #: field:account.chart.template,tax_code_root_id:0 @@ -1598,17 +1606,17 @@ msgstr "Kaasa algsed" #. module: account #: field:account.tax.code,sum:0 msgid "Year Sum" -msgstr "" +msgstr "Aasta kokkuvõtte" #. module: account #: model:ir.actions.report.xml,name:account.report_account_voucher_new msgid "Print Voucher" -msgstr "" +msgstr "Prindi voucher" #. module: account #: view:account.change.currency:0 msgid "This wizard will change the currency of the invoice" -msgstr "" +msgstr "See wizard muudab valuuta arvelduses" #. module: account #: model:ir.actions.act_window,help:account.action_account_chart @@ -1632,7 +1640,7 @@ msgstr "" #. module: account #: field:account.cashbox.line,pieces:0 msgid "Values" -msgstr "" +msgstr "Väärtused" #. module: account #: help:account.journal.period,active:0 @@ -1675,7 +1683,7 @@ msgstr "" #. module: account #: report:account.move.voucher:0 msgid "Ref. :" -msgstr "" +msgstr "Viide:" #. module: account #: view:account.analytic.chart:0 @@ -1685,7 +1693,7 @@ msgstr "Analüütilised kontoplaanid" #. module: account #: view:account.analytic.line:0 msgid "My Entries" -msgstr "" +msgstr "Minu sisestused" #. module: account #: report:account.overdue:0 @@ -1696,7 +1704,7 @@ msgstr "Kliendi viide:" #: code:addons/account/account_cash_statement.py:328 #, python-format msgid "User %s does not have rights to access %s journal !" -msgstr "" +msgstr "Kasutajal %s ei ole õigusi et siseneda %s arveraamatusse !" #. module: account #: help:account.period,special:0 @@ -1717,12 +1725,12 @@ msgstr "" #: code:addons/account/account.py:499 #, python-format msgid "You cannot deactivate an account that contains account moves." -msgstr "" +msgstr "Sa ei saa deaktiveerida kontot mis sisaldab konto liikumisi." #. module: account #: field:account.move.line.reconcile,credit:0 msgid "Credit amount" -msgstr "" +msgstr "Kreedidi kogus" #. module: account #: constraint:account.move.line:0 @@ -1745,7 +1753,7 @@ msgstr "" #. module: account #: sql_constraint:account.move.line:0 msgid "Wrong credit or debit value in accounting entry !" -msgstr "" +msgstr "Vale kreedit või deebeti raamatupidamise sisend !" #. module: account #: view:account.invoice.report:0 @@ -1757,7 +1765,7 @@ msgstr "" #. module: account #: model:ir.model,name:account.model_account_period_close msgid "period close" -msgstr "" +msgstr "Periood suletud" #. module: account #: view:account.installer:0 @@ -1767,18 +1775,18 @@ msgstr "" #. module: account #: model:ir.actions.act_window,name:account.action_project_account_analytic_line_form msgid "Entries By Line" -msgstr "" +msgstr "SIsestused ridade kaupa" #. module: account #: report:account.tax.code.entries:0 msgid "A/c Code" -msgstr "" +msgstr "A/c kood" #. module: account #: field:account.invoice,move_id:0 #: field:account.invoice,move_name:0 msgid "Journal Entry" -msgstr "" +msgstr "Päevaraamatu kanne" #. module: account #: view:account.tax:0 @@ -1788,7 +1796,7 @@ msgstr "" #. module: account #: field:account.cashbox.line,subtotal:0 msgid "Sub Total" -msgstr "" +msgstr "Vahesumma" #. module: account #: view:account.account:0 @@ -1798,7 +1806,7 @@ msgstr "" #. module: account #: constraint:res.company:0 msgid "Error! You can not create recursive companies." -msgstr "" +msgstr "Viga! Sa ei saa luua rekursiivseid ettevõtteid." #. module: account #: view:account.analytic.account:0 @@ -1821,12 +1829,12 @@ msgstr "Kehtiv" #: model:ir.actions.act_window,name:account.action_account_print_journal #: model:ir.model,name:account.model_account_print_journal msgid "Account Print Journal" -msgstr "" +msgstr "Prindi konto arveraamat" #. module: account #: model:ir.model,name:account.model_product_category msgid "Product Category" -msgstr "" +msgstr "Toote kategooria" #. module: account #: selection:account.account.type,report_type:0 @@ -1836,7 +1844,7 @@ msgstr "/" #. module: account #: field:account.bs.report,reserve_account_id:0 msgid "Reserve & Profit/Loss Account" -msgstr "" +msgstr "Reservi & kasumi/kahjumi konto" #. module: account #: help:account.bank.statement,balance_end:0 diff --git a/openerp/addons/base/i18n/zh_TW.po b/openerp/addons/base/i18n/zh_TW.po index ab4f83dd89d..04b75725807 100644 --- a/openerp/addons/base/i18n/zh_TW.po +++ b/openerp/addons/base/i18n/zh_TW.po @@ -7,14 +7,14 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.0\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2011-01-11 11:14+0000\n" -"PO-Revision-Date: 2011-09-28 13:58+0000\n" +"PO-Revision-Date: 2011-09-29 15:26+0000\n" "Last-Translator: Walter Cheuk \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2011-09-29 04:36+0000\n" -"X-Generator: Launchpad (build 14049)\n" +"X-Launchpad-Export-Date: 2011-09-30 04:37+0000\n" +"X-Generator: Launchpad (build 14071)\n" #. module: base #: view:ir.filters:0 @@ -2795,7 +2795,7 @@ msgstr "向用戶提供目標視窗之額外說明文字,如其用法及用途 #. module: base #: model:res.country,name:base.va msgid "Holy See (Vatican City State)" -msgstr "教廷(梵蒂岡)" +msgstr "教廷 (梵蒂岡)" #. module: base #: field:base.module.import,module_file:0 From d32f04bb3c33f810ae41b0586a6205a47c54a04d Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Fri, 30 Sep 2011 10:04:25 +0200 Subject: [PATCH 043/161] [IMP] reverting back useability on company header/footer from al bzr revid: fp@tinyerp.com-20110930080425-wuyaef8fd2k1fuwy --- openerp/addons/base/base_update.xml | 19 ++++++------ openerp/addons/base/res/res_company.py | 41 +++++++++++++------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/openerp/addons/base/base_update.xml b/openerp/addons/base/base_update.xml index 444c7b5189c..434bd6687b3 100644 --- a/openerp/addons/base/base_update.xml +++ b/openerp/addons/base/base_update.xml @@ -225,18 +225,17 @@ - - - - - - + + + + + + - -