From 88c022dfc80a9397c4c45bbdb145b63d4c248464 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Tue, 29 Jul 2014 11:42:10 +0200 Subject: [PATCH] [MERGE] forward port of branch 7.0 up to bbb8d8f25a7a81c26965aa76b5085961a13132d6 --- addons/account/account_invoice_view.xml | 8 ++-- addons/account/account_move_line.py | 4 +- addons/base_vat/base_vat.py | 42 +++++++++++++++++-- addons/delivery/delivery.py | 2 +- addons/gamification/views/badge.xml | 1 - addons/hr_holidays/hr_holidays.py | 2 +- addons/mail/mail_thread.py | 5 ++- addons/project/report/project_report.py | 1 - .../purchase_analytic_plans.py | 10 +++++ addons/stock/stock.py | 3 +- addons/web/static/src/js/views.js | 4 +- addons/website/static/src/css/snippets.css | 7 ++++ addons/website/static/src/css/snippets.sass | 6 +++ addons/website_membership/controllers/main.py | 14 ++++--- openerp/addons/base/ir/ir_fields.py | 8 ++-- openerp/addons/base/ir/ir_values.py | 4 +- openerp/tools/safe_eval.py | 3 +- 17 files changed, 94 insertions(+), 30 deletions(-) diff --git a/addons/account/account_invoice_view.xml b/addons/account/account_invoice_view.xml index fe701a85661..687151eebd8 100644 --- a/addons/account/account_invoice_view.xml +++ b/addons/account/account_invoice_view.xml @@ -61,7 +61,7 @@ - + @@ -95,7 +95,7 @@ - + @@ -201,7 +201,7 @@ domain="[('company_id', '=', parent.company_id), ('journal_id', '=', parent.journal_id), ('type', '=', 'other')]" on_change="onchange_account_id(product_id, parent.partner_id, parent.type, parent.fiscal_position,account_id)"/> + domain="[('type','!=','view'), ('company_id', '=', parent.company_id), ('state','not in',('close','cancelled'))]"/> @@ -358,7 +358,7 @@ domain="[('company_id', '=', parent.company_id), ('journal_id', '=', parent.journal_id), ('type', '=', 'other')]" on_change="onchange_account_id(product_id, parent.partner_id, parent.type, parent.fiscal_position,account_id)"/> + domain="[('type','!=','view'), ('company_id', '=', parent.company_id), ('state','not in',('close','cancelled'))]"/> diff --git a/addons/account/account_move_line.py b/addons/account/account_move_line.py index 3483472fb30..b7d4e6b7fb9 100644 --- a/addons/account/account_move_line.py +++ b/addons/account/account_move_line.py @@ -573,7 +573,7 @@ class account_move_line(osv.osv): def _check_no_view(self, cr, uid, ids, context=None): lines = self.browse(cr, uid, ids, context=context) for l in lines: - if l.account_id.type == 'view': + if l.account_id.type in ('view', 'consolidation'): return False return True @@ -625,7 +625,7 @@ class account_move_line(osv.osv): return True _constraints = [ - (_check_no_view, 'You cannot create journal items on an account of type view.', ['account_id']), + (_check_no_view, 'You cannot create journal items on an account of type view or consolidation.', ['account_id']), (_check_no_closed, 'You cannot create journal items on closed account.', ['account_id']), (_check_company_id, 'Account and Period must belong to the same company.', ['company_id']), (_check_date, 'The date of your Journal Entry is not in the defined period! You should change the date or remove this constraint from the journal.', ['date']), diff --git a/addons/base_vat/base_vat.py b/addons/base_vat/base_vat.py index 9b3862508b0..4e211edf68b 100644 --- a/addons/base_vat/base_vat.py +++ b/addons/base_vat/base_vat.py @@ -63,6 +63,7 @@ _ref_vat = { 'mx': 'MXABC123456T1B', 'nl': 'NL123456782B90', 'no': 'NO123456785', + 'pe': 'PER10254824220 or PED10254824220', 'pl': 'PL1234567883', 'pt': 'PT123456789', 'ro': 'RO1234567897', @@ -148,10 +149,11 @@ class res_partner(osv.osv): return cn[0] in string.ascii_lowercase and cn[1] in string.ascii_lowercase vat_country, vat_number = self._split_vat(self.browse(cr, uid, ids)[0].vat) vat_no = "'CC##' (CC=Country Code, ##=VAT Number)" + error_partner = self.browse(cr, uid, ids, context=context) if default_vat_check(vat_country, vat_number): vat_no = _ref_vat[vat_country] if vat_country in _ref_vat else vat_no - #Retrieve the current partner for wich the VAT is not valid - error_partner = self.browse(cr, uid, ids, context=context) + if self.pool['res.users'].browse(cr, uid, uid).company_id.vat_check_vies: + return '\n' + _('The VAT number [%s] for partner [%s] either failed the VIES VAT validation check or did not respect the expected format %s.') % (error_partner[0].vat, error_partner[0].name, vat_no) return '\n' + _('The VAT number [%s] for partner [%s] does not seem to be valid. \nNote: the expected format is %s') % (error_partner[0].vat, error_partner[0].name, vat_no) _constraints = [(check_vat, _construct_constraint_msg, ["vat"])] @@ -222,7 +224,7 @@ class res_partner(osv.osv): return vat[7] == self._ie_check_char(vat[2:7] + vat[0] + vat[8]) return False - # Mexican VAT verification, contributed by + # Mexican VAT verification, contributed by Vauxoo # and Panos Christeas __check_vat_mx_re = re.compile(r"(?P[A-Za-z\xd1\xf1&]{3,4})" \ r"[ \-_]?" \ @@ -279,5 +281,39 @@ class res_partner(osv.osv): return False return check == int(vat[8]) + # Peruvian VAT validation, contributed by Vauxoo + def check_vat_pe(self, vat): + + vat_type,vat = vat and len(vat)>=2 and (vat[0], vat[1:]) or (False, False) + + if vat_type and vat_type.upper() == 'D': + #DNI + return True + elif vat_type and vat_type.upper() == 'R': + #verify RUC + factor = '5432765432' + sum = 0 + dig_check = False + if len(vat) != 11: + return False + try: + int(vat) + except ValueError: + return False + + for f in range(0,10): + sum += int(factor[f]) * int(vat[f]) + + subtraction = 11 - (sum % 11) + if subtraction == 10: + dig_check = 0 + elif subtraction == 11: + dig_check = 1 + else: + dig_check = subtraction + + return int(vat[10]) == dig_check + else: + return False # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/delivery/delivery.py b/addons/delivery/delivery.py index 59542eefc90..7b3791bfcee 100644 --- a/addons/delivery/delivery.py +++ b/addons/delivery/delivery.py @@ -195,7 +195,7 @@ class delivery_grid(osv.osv): for line in order.order_line: if not line.product_id or line.is_delivery: continue - q = product_uom_obj._compute_qty(cr, uid, line.product_uom.id, line.product_uos_qty, line.product_id.uom_id.id) + q = product_uom_obj._compute_qty(cr, uid, line.product_uom.id, line.product_uom_qty, line.product_id.uom_id.id) weight += (line.product_id.weight or 0.0) * q volume += (line.product_id.volume or 0.0) * q total = order.amount_total or 0.0 diff --git a/addons/gamification/views/badge.xml b/addons/gamification/views/badge.xml index 0b37e62051d..ad0aee76b07 100644 --- a/addons/gamification/views/badge.xml +++ b/addons/gamification/views/badge.xml @@ -40,7 +40,6 @@
diff --git a/addons/hr_holidays/hr_holidays.py b/addons/hr_holidays/hr_holidays.py index b548f15f7df..812f0438a41 100644 --- a/addons/hr_holidays/hr_holidays.py +++ b/addons/hr_holidays/hr_holidays.py @@ -504,7 +504,7 @@ class hr_employee(osv.osv): if diff > 0: leave_id = holiday_obj.create(cr, uid, {'name': _('Allocation for %s') % employee.name, 'employee_id': employee.id, 'holiday_status_id': status_id, 'type': 'add', 'holiday_type': 'employee', 'number_of_days_temp': diff}, context=context) elif diff < 0: - leave_id = holiday_obj.create(cr, uid, {'name': _('Leave Request for %s') % employee.name, 'employee_id': employee.id, 'holiday_status_id': status_id, 'type': 'remove', 'holiday_type': 'employee', 'number_of_days_temp': abs(diff)}, context=context) + raise osv.except_osv(_('Warning!'), _('You cannot reduce validated allocation requests')) else: return False holiday_obj.signal_confirm(cr, uid, [leave_id]) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 2c0b40ab44c..e5b06d65f6d 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -373,7 +373,10 @@ class mail_thread(osv.AbstractModel): # automatic logging unless asked not to (mainly for various testing purpose) if not context.get('mail_create_nolog'): - self.message_post(cr, uid, thread_id, body=_('%s created') % (self._description), context=context) + ir_model_pool = self.pool['ir.model'] + ids = ir_model_pool.search(cr, uid, [('model', '=', self._name)], context=context) + name = ir_model_pool.read(cr, uid, ids, ['name'], context=context)[0]['name'] + self.message_post(cr, uid, thread_id, body=_('%s created') % name, context=context) # auto_subscribe: take values and defaults into account create_values = dict(values) diff --git a/addons/project/report/project_report.py b/addons/project/report/project_report.py index 5a473469b2d..30a61106d76 100644 --- a/addons/project/report/project_report.py +++ b/addons/project/report/project_report.py @@ -50,7 +50,6 @@ class report_project_task_user(osv.osv): 'nbr': fields.integer('# of tasks', readonly=True), 'priority': fields.selection([('4', 'Very Low'), ('3', 'Low'), ('2', 'Medium'), ('1', 'Urgent'), ('0', 'Very urgent')], string='Priority', readonly=True), - 'state': fields.selection([('draft', 'Draft'), ('open', 'In Progress'), ('pending', 'Pending'), ('cancelled', 'Cancelled'), ('done', 'Done')],'Status', readonly=True), 'company_id': fields.many2one('res.company', 'Company', readonly=True), 'partner_id': fields.many2one('res.partner', 'Contact', readonly=True), 'stage_id': fields.many2one('project.task.type', 'Stage'), diff --git a/addons/purchase_analytic_plans/purchase_analytic_plans.py b/addons/purchase_analytic_plans/purchase_analytic_plans.py index a654de83253..ce9de30f5e3 100644 --- a/addons/purchase_analytic_plans/purchase_analytic_plans.py +++ b/addons/purchase_analytic_plans/purchase_analytic_plans.py @@ -40,4 +40,14 @@ class purchase_order(osv.osv): return res +class stock_picking(osv.osv): + _name='stock.picking' + _inherit='stock.picking' + + def _prepare_invoice_line(self, cr, uid, group, picking, move_line, invoice_id, invoice_vals, context=None): + res = super(stock_picking, self)._prepare_invoice_line(cr, uid, group, picking, move_line, invoice_id, invoice_vals, context=context) + if move_line.purchase_line_id and move_line.purchase_line_id.analytics_id: + res['analytics_id'] = move_line.purchase_line_id.analytics_id.id + return res + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/stock/stock.py b/addons/stock/stock.py index 34a24354508..ee8dc4b8348 100644 --- a/addons/stock/stock.py +++ b/addons/stock/stock.py @@ -1005,7 +1005,6 @@ class stock_picking(osv.osv): 'origin': (invoice.origin or '') + ', ' + (picking.name or '') + (picking.origin and (':' + picking.origin) or ''), 'comment': (comment and (invoice.comment and invoice.comment + "\n" + comment or comment)) or (invoice.comment and invoice.comment or ''), 'date_invoice': context.get('date_inv', False), - 'user_id': uid, } def _prepare_invoice(self, cr, uid, picking, partner, inv_type, journal_id, context=None): @@ -1480,7 +1479,7 @@ class stock_production_lot(osv.osv): 'product_id': lambda x, y, z, c: c.get('product_id', False), } _sql_constraints = [ - ('name_ref_uniq', 'unique (name, ref)', 'The combination of Serial Number and internal reference must be unique !'), + ('name_ref_uniq', 'unique (name, ref, product_id, company_id)', 'The combination of Serial Number, internal reference, Product and Company must be unique !'), ] def action_traceability(self, cr, uid, ids, context=None): """ It traces the information of a product diff --git a/addons/web/static/src/js/views.js b/addons/web/static/src/js/views.js index 51ee2b3ce1b..b8f30309b93 100644 --- a/addons/web/static/src/js/views.js +++ b/addons/web/static/src/js/views.js @@ -689,8 +689,8 @@ instance.web.ViewManager = instance.web.Widget.extend({ var container = this.$el.find("> .oe_view_manager_body > .oe_view_manager_view_" + view_type); var view_promise = controller.appendTo(container); this.views[view_type].controller = controller; - this.views[view_type].deferred.resolve(view_type); return $.when(view_promise).done(function() { + self.views[view_type].deferred.resolve(view_type); if (self.searchview && self.flags.auto_search && view.controller.searchable !== false) { @@ -1117,7 +1117,7 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({ ); } - $.when(defs).done(function() { + $.when(this.views[this.active_view] ? this.views[this.active_view].deferred : $.when(), defs).done(function() { self.views[self.active_view].controller.do_load_state(state, warm); }); }, diff --git a/addons/website/static/src/css/snippets.css b/addons/website/static/src/css/snippets.css index cbfca8be131..777ded66138 100644 --- a/addons/website/static/src/css/snippets.css +++ b/addons/website/static/src/css/snippets.css @@ -375,6 +375,13 @@ } .oe_overlay .oe_overlay_options > .btn-group { left: -50%; + white-space: nowrap; +} +.oe_overlay .oe_overlay_options > .btn-group > a { + cursor: pointer; + display: inline-block; + float: none; + margin: 0 -3px; } .oe_overlay .oe_overlay_options .btn, .oe_overlay .oe_overlay_options a { cursor: pointer; diff --git a/addons/website/static/src/css/snippets.sass b/addons/website/static/src/css/snippets.sass index 40467897e26..33a45e426df 100644 --- a/addons/website/static/src/css/snippets.sass +++ b/addons/website/static/src/css/snippets.sass @@ -279,6 +279,12 @@ z-index: 1002 > .btn-group left: -50% + white-space: nowrap + > a + cursor: pointer + display: inline-block + float: none + margin: 0 -3px .btn, a cursor: pointer .dropdown diff --git a/addons/website_membership/controllers/main.py b/addons/website_membership/controllers/main.py index 1ab0e5e36af..ca1566b2f31 100644 --- a/addons/website_membership/controllers/main.py +++ b/addons/website_membership/controllers/main.py @@ -48,7 +48,7 @@ class WebsiteMembership(http.Controller): ('partner.website_description', 'ilike', post_name)] # group by country, based on all customers (base domain) - membership_line_ids = membership_line_obj.search(cr, uid, base_line_domain, context=context) + membership_line_ids = membership_line_obj.search(cr, SUPERUSER_ID, base_line_domain, context=context) countries = partner_obj.read_group( cr, uid, [('member_lines', 'in', membership_line_ids), ("website_published", "=", True)], ["id", "country_id"], groupby="country_id", orderby="country_id", context=request.context) @@ -70,8 +70,14 @@ class WebsiteMembership(http.Controller): 'country_id': (0, _("All Countries")) }) + # format domain for group_by and memberships + membership_ids = product_obj.search(cr, uid, [('membership', '=', True)], order="website_sequence", context=context) + memberships = product_obj.browse(cr, uid, membership_ids, context=context) + # make sure we don't access to lines with unpublished membershipts + line_domain.append(('membership_id', 'in', membership_ids)) + # displayed membership lines - membership_line_ids = membership_line_obj.search(cr, uid, line_domain, context=context) + membership_line_ids = membership_line_obj.search(cr, SUPERUSER_ID, line_domain, context=context) membership_lines = membership_line_obj.browse(cr, uid, membership_line_ids, context=context) membership_lines.sort(key=lambda x: x.membership_id.website_sequence) partner_ids = [m.partner.id for m in membership_lines] @@ -79,10 +85,6 @@ class WebsiteMembership(http.Controller): partners = dict((p.id, p) for p in partner_obj.browse(request.cr, SUPERUSER_ID, partner_ids, request.context)) - # format domain for group_by and memberships - membership_ids = product_obj.search(cr, uid, [('membership', '=', True)], order="website_sequence", context=context) - memberships = product_obj.browse(cr, uid, membership_ids, context=context) - # request pager for lines pager = request.website.pager(url="/members", total=len(membership_line_ids), page=page, step=self._references_per_page, scope=7, url_args=post) diff --git a/openerp/addons/base/ir/ir_fields.py b/openerp/addons/base/ir/ir_fields.py index 217ea319d8e..222fc90d797 100644 --- a/openerp/addons/base/ir/ir_fields.py +++ b/openerp/addons/base/ir/ir_fields.py @@ -12,7 +12,8 @@ import pytz from openerp.osv import orm from openerp.tools.translate import _ from openerp.tools.misc import DEFAULT_SERVER_DATE_FORMAT,\ - DEFAULT_SERVER_DATETIME_FORMAT + DEFAULT_SERVER_DATETIME_FORMAT,\ + ustr from openerp.tools import html_sanitize REFERENCING_FIELDS = set([None, 'id', '.id']) @@ -260,6 +261,7 @@ class ir_fields_converter(orm.Model): # Or just copy context & remove lang? selection = selection(model, cr, uid, context=None) for item, label in selection: + label = ustr(label) labels = self._get_translations( cr, uid, ('selection', 'model', 'code'), label, context=context) labels.append(label) @@ -268,8 +270,8 @@ class ir_fields_converter(orm.Model): raise ValueError( _(u"Value '%s' not found in selection field '%%(field)s'") % ( value), { - 'moreinfo': [label or unicode(item) for item, label in selection - if label or item] + 'moreinfo': [_label or unicode(item) for item, _label in selection + if _label or item] }) diff --git a/openerp/addons/base/ir/ir_values.py b/openerp/addons/base/ir/ir_values.py index 9411886a304..6af09b7ecbb 100644 --- a/openerp/addons/base/ir/ir_values.py +++ b/openerp/addons/base/ir/ir_values.py @@ -303,10 +303,10 @@ class ir_values(osv.osv): (SELECT company_id from res_users where id = %%s) ) %s - ORDER BY v.user_id, u.company_id, v.key2""" + ORDER BY v.user_id, u.company_id""" params = ('default', model, uid, uid) if condition: - query %= 'AND (v.key2 = %s OR v.key2 IS NULL)' + query %= 'AND v.key2 = %s' params += (condition[:200],) else: query %= 'AND v.key2 is NULL' diff --git a/openerp/tools/safe_eval.py b/openerp/tools/safe_eval.py index 471827b098b..4f39e1fd557 100644 --- a/openerp/tools/safe_eval.py +++ b/openerp/tools/safe_eval.py @@ -72,7 +72,7 @@ _SAFE_OPCODES = _EXPR_OPCODES.union(set(opmap[x] for x in [ # New in Python 2.7 - http://bugs.python.org/issue4715 : 'JUMP_IF_FALSE_OR_POP', 'JUMP_IF_TRUE_OR_POP', 'POP_JUMP_IF_FALSE', 'POP_JUMP_IF_TRUE', 'SETUP_EXCEPT', 'END_FINALLY', - 'LOAD_FAST', 'STORE_FAST', 'DELETE_FAST', + 'LOAD_FAST', 'STORE_FAST', 'DELETE_FAST', 'UNPACK_SEQUENCE', 'LOAD_GLOBAL', # Only allows access to restricted globals ] if x in opmap)) @@ -300,6 +300,7 @@ def safe_eval(expr, globals_dict=None, locals_dict=None, mode="eval", nocopy=Fal 'range': range, 'xrange': xrange, 'zip': zip, + 'Exception': Exception, } ) if locals_builtins: