[MERGE] forward port of branch 7.0 up to bbb8d8f25a7a81c26965aa76b5085961a13132d6
authorDenis Ledoux <dle@odoo.com>
Tue, 29 Jul 2014 09:42:10 +0000 (11:42 +0200)
committerDenis Ledoux <dle@odoo.com>
Tue, 29 Jul 2014 09:42:10 +0000 (11:42 +0200)
17 files changed:
addons/account/account_invoice_view.xml
addons/account/account_move_line.py
addons/base_vat/base_vat.py
addons/delivery/delivery.py
addons/gamification/views/badge.xml
addons/hr_holidays/hr_holidays.py
addons/mail/mail_thread.py
addons/project/report/project_report.py
addons/purchase_analytic_plans/purchase_analytic_plans.py
addons/stock/stock.py
addons/web/static/src/js/views.js
addons/website/static/src/css/snippets.css
addons/website/static/src/css/snippets.sass
addons/website_membership/controllers/main.py
openerp/addons/base/ir/ir_fields.py
openerp/addons/base/ir/ir_values.py
openerp/tools/safe_eval.py

index fe701a8..687151e 100644 (file)
@@ -61,7 +61,7 @@
                         <group>
                             <field domain="[('company_id', '=', parent.company_id), ('journal_id', '=', parent.journal_id), ('type', '&lt;&gt;', 'view')]" name="account_id" on_change="onchange_account_id(product_id, parent.partner_id, parent.type, parent.fiscal_position,account_id)" groups="account.group_account_user"/>
                             <field name="invoice_line_tax_id" context="{'type':parent.get('type')}" domain="[('parent_id','=',False),('company_id', '=', parent.company_id)]" widget="many2many_tags"/>
-                            <field domain="[('type','&lt;&gt;','view'), ('company_id', '=', parent.company_id)]" name="account_analytic_id" groups="analytic.group_analytic_accounting"/>
+                            <field domain="[('type','&lt;&gt;','view'), ('company_id', '=', parent.company_id)], ('state','not in',('close','cancelled'))]" name="account_analytic_id" groups="analytic.group_analytic_accounting"/>
                             <field name="company_id" groups="base.group_multi_company" readonly="1"/>
                         </group>
                     </group>
@@ -95,7 +95,7 @@
                         <field name="name"/>
                         <field name="sequence"/>
                         <field name="account_id" groups="account.group_account_user"/>
-                        <field name="account_analytic_id" domain="[('type','&lt;&gt;','view'), ('company_id', '=', parent.company_id)]" groups="analytic.group_analytic_accounting"/>
+                        <field name="account_analytic_id" domain="[('type','&lt;&gt;','view'), ('company_id', '=', parent.company_id), ('state','not in',('close','cancelled')]" groups="analytic.group_analytic_accounting"/>
                         <field name="manual"/>
                         <field name="amount"/>
                         <field name="base" readonly="0"/>
                                         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)"/>
                                     <field name="account_analytic_id" groups="analytic.group_analytic_accounting"
-                                        domain="[('type','!=','view'), ('company_id', '=', parent.company_id)]"/>
+                                        domain="[('type','!=','view'), ('company_id', '=', parent.company_id), ('state','not in',('close','cancelled'))]"/>
                                     <field name="quantity"/>
                                     <field name="uos_id" groups="product.group_uom"
                                         on_change="uos_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id, parent.fiscal_position, price_unit, parent.currency_id, context, parent.company_id)"/>
                                         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)"/>
                                     <field name="account_analytic_id" groups="analytic.group_analytic_accounting"
-                                        domain="[('type','!=','view'), ('company_id', '=', parent.company_id)]"/>
+                                        domain="[('type','!=','view'), ('company_id', '=', parent.company_id), ('state','not in',('close','cancelled'))]"/>
                                     <field name="quantity"/>
                                     <field name="uos_id" groups="product.group_uom"
                                         on_change="uos_id_change(product_id, uos_id, quantity, name, parent.type, parent.partner_id, parent.fiscal_position, price_unit, parent.currency_id, context, parent.company_id)"/>
index 3483472..b7d4e6b 100644 (file)
@@ -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']),
index 9b38625..4e211ed 100644 (file)
@@ -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 <moylop260@hotmail.com>
+    # Mexican VAT verification, contributed by Vauxoo
     # and Panos Christeas <p_christ@hol.gr>
     __check_vat_mx_re = re.compile(r"(?P<primeras>[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:
index 59542ee..7b3791b 100644 (file)
@@ -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
index 0b37e62..ad0aee7 100644 (file)
@@ -40,7 +40,6 @@
                 <form string="Badge" version="7.0">
                     <header>
                         <button string="Grant this Badge" type="action" name="%(action_grant_wizard)d" class="oe_highlight" attrs="{'invisible': [('remaining_sending','=',0)]}" />
-                        <button string="Check Badge" type="object" name="check_automatic" groups="base.group_no_one" />
                     </header>
                     <sheet>
                         <div class="oe_right oe_button_box">
index b548f15..812f043 100644 (file)
@@ -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])
index 2c0b40a..e5b06d6 100644 (file)
@@ -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)
index 5a47346..30a6110 100644 (file)
@@ -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'),
index a654de8..ce9de30 100644 (file)
@@ -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:
index 34a2435..ee8dc4b 100644 (file)
@@ -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
index 51ee2b3..b8f3030 100644 (file)
@@ -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);
         });
     },
index cbfca8b..777ded6 100644 (file)
 }
 .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;
index 4046789..33a45e4 100644 (file)
         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
index 1ab0e5e..ca1566b 100644 (file)
@@ -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)
 
index 217ea31..222fc90 100644 (file)
@@ -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]
             })
 
 
index 9411886..6af09b7 100644 (file)
@@ -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'
index 471827b..4f39e1f 100644 (file)
@@ -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: