[MERGE] forward port of branch 7.0 up to 9b1cdea

This commit is contained in:
Christophe Simonis 2014-09-12 17:28:55 +02:00
commit fdc62713a5
9 changed files with 34 additions and 29 deletions

View File

@ -311,16 +311,19 @@ class hr_expense_expense(osv.osv):
line.unit_quantity, line.product_id, line.unit_quantity, line.product_id,
exp.user_id.partner_id)['taxes']: exp.user_id.partner_id)['taxes']:
tax_code_id = tax['base_code_id'] tax_code_id = tax['base_code_id']
tax_amount = line.total_amount * tax['base_sign']
if not tax_code_id: if not tax_code_id:
continue continue
res[-1]['tax_code_id'] = tax_code_id res[-1]['tax_code_id'] = tax_code_id
res[-1]['tax_amount'] = cur_obj.compute(cr, uid, exp.currency_id.id, company_currency, tax_amount, context={'date': exp.date_confirm})
## ##
is_price_include = tax_obj.read(cr,uid,tax['id'],['price_include'],context)['price_include'] is_price_include = tax_obj.read(cr,uid,tax['id'],['price_include'],context)['price_include']
if is_price_include: if is_price_include:
## We need to deduce the price for the tax ## We need to deduce the price for the tax
res[-1]['price'] = res[-1]['price'] - (tax['amount'] * tax['base_sign'] or 0.0) res[-1]['price'] = res[-1]['price'] - (tax['amount'] * tax['base_sign'] or 0.0)
# tax amount countains base amount without the tax
tax_amount = (line.total_amount - tax['amount']) * tax['base_sign']
else:
tax_amount = line.total_amount * tax['base_sign']
res[-1]['tax_amount'] = cur_obj.compute(cr, uid, exp.currency_id.id, company_currency, tax_amount, context={'date': exp.date_confirm})
assoc_tax = { assoc_tax = {
'type':'tax', 'type':'tax',
'name':tax['name'], 'name':tax['name'],

View File

@ -28,26 +28,15 @@ class res_partner(osv.osv):
'nrc' : fields.char('NRC', size=16, help='Registration number at the Registry of Commerce'), 'nrc' : fields.char('NRC', size=16, help='Registration number at the Registry of Commerce'),
} }
# The SQL constraints are no-ops but present only to display the right error message to the
# user when the partial unique indexes defined below raise errors/
# The real constraints need to be implemented with PARTIAL UNIQUE INDEXES (see auto_init),
# due to the way accounting data is delegated by contacts to their companies in OpenERP 7.0.
_sql_constraints = [
('vat_uniq', 'unique (id)', 'The vat of the partner must be unique !'),
('nrc_uniq', 'unique (id)', 'The code of the partner must be unique !')
]
def _auto_init(self, cr, context=None): def _auto_init(self, cr, context=None):
result = super(res_partner, self)._auto_init(cr, context=context) result = super(res_partner, self)._auto_init(cr, context=context)
# Real implementation of the vat/nrc constraints: only "commercial entities" need to have # Remove constrains for vat, nrc on "commercial entities" because is not mandatory by legislation
# unique numbers, and the condition for being a commercial entity is "is_company or parent_id IS NULL". # Even that VAT numbers are unique, the NRC field is not unique, and there are certain entities that
# Contacts inside a company automatically have a copy of the company's commercial fields # doesn't have a NRC number plus the formatting was changed few times, so we cannot have a base rule for
# (see _commercial_fields()), so they are automatically consistent. # checking if available and emmited by the Ministry of Finance, only online on their website.
cr.execute(""" cr.execute("""
DROP INDEX IF EXISTS res_partner_vat_uniq_for_companies; DROP INDEX IF EXISTS res_partner_vat_uniq_for_companies;
DROP INDEX IF EXISTS res_partner_nrc_uniq_for_companies; DROP INDEX IF EXISTS res_partner_nrc_uniq_for_companies;
CREATE UNIQUE INDEX res_partner_vat_uniq_for_companies ON res_partner (vat) WHERE is_company OR parent_id IS NULL;
CREATE UNIQUE INDEX res_partner_nrc_uniq_for_companies ON res_partner (nrc) WHERE is_company OR parent_id IS NULL;
""") """)
return result return result

View File

@ -392,7 +392,7 @@ class mrp_repair(osv.osv):
'origin':repair.name, 'origin':repair.name,
'type': 'out_invoice', 'type': 'out_invoice',
'account_id': account_id, 'account_id': account_id,
'partner_id': repair.partner_id.id, 'partner_id': repair.partner_invoice_id.id or repair.partner_id.id,
'currency_id': repair.pricelist_id.currency_id.id, 'currency_id': repair.pricelist_id.currency_id.id,
'comment': repair.quotation_notes, 'comment': repair.quotation_notes,
'fiscal_position': repair.partner_id.property_account_position.id 'fiscal_position': repair.partner_id.property_account_position.id

View File

@ -203,6 +203,7 @@ class stock_return_picking(osv.osv_memory):
'location_id': new_location, 'location_id': new_location,
'location_dest_id': move.location_id.id, 'location_dest_id': move.location_id.id,
'date': date_cur, 'date': date_cur,
'prodlot_id': data_get.prodlot_id.id,
}) })
move_obj.write(cr, uid, [move.id], {'move_history_ids2':[(4,new_move)]}, context=context) move_obj.write(cr, uid, [move.id], {'move_history_ids2':[(4,new_move)]}, context=context)
if not returned_lines: if not returned_lines:

View File

@ -159,7 +159,7 @@ class survey_question_wiz(osv.osv_memory):
title = sur_rec.title title = sur_rec.title
xml_form = etree.Element('form', {'string': tools.ustr(title)}) xml_form = etree.Element('form', {'string': tools.ustr(title)})
if context.has_key('active') and context.get('active',False) and context.has_key('edit'): if context.has_key('active') and context.get('active',False) and context.has_key('edit'):
context.update({'page_id' : tools.ustr(p_id),'page_number' : sur_name_rec.page_no , 'transfer' : sur_name_read.transfer}) context.update({'page_id' : p_id,'page_number' : sur_name_rec.page_no , 'transfer' : sur_name_read.transfer})
xml_group3 = etree.SubElement(xml_form, 'group', {'col': '4', 'colspan': '4'}) xml_group3 = etree.SubElement(xml_form, 'group', {'col': '4', 'colspan': '4'})
etree.SubElement(xml_group3, 'button', {'string' :'Add Page','icon': "gtk-new", 'type' :'object','name':"action_new_page", 'context' : tools.ustr(context)}) etree.SubElement(xml_group3, 'button', {'string' :'Add Page','icon': "gtk-new", 'type' :'object','name':"action_new_page", 'context' : tools.ustr(context)})
etree.SubElement(xml_group3, 'button', {'string' :'Edit Page','icon': "gtk-edit", 'type' :'object','name':"action_edit_page", 'context' : tools.ustr(context)}) etree.SubElement(xml_group3, 'button', {'string' :'Edit Page','icon': "gtk-edit", 'type' :'object','name':"action_edit_page", 'context' : tools.ustr(context)})

View File

@ -1015,7 +1015,7 @@ instance.web.UserMenu = instance.web.Widget.extend({
this.update_promise = this.update_promise.then(fct, fct); this.update_promise = this.update_promise.then(fct, fct);
}, },
on_menu_help: function() { on_menu_help: function() {
window.open('http://help.openerp.com', '_blank'); window.open('http://help.odoo.com', '_blank');
}, },
on_menu_logout: function() { on_menu_logout: function() {
this.trigger('user_logout'); this.trigger('user_logout');
@ -1044,10 +1044,10 @@ instance.web.UserMenu = instance.web.Widget.extend({
state: JSON.stringify(state), state: JSON.stringify(state),
scope: 'userinfo', scope: 'userinfo',
}; };
instance.web.redirect('https://accounts.openerp.com/oauth2/auth?'+$.param(params)); instance.web.redirect('https://accounts.odoo.com/oauth2/auth?'+$.param(params));
}).fail(function(result, ev){ }).fail(function(result, ev){
ev.preventDefault(); ev.preventDefault();
instance.web.redirect('https://accounts.openerp.com/web'); instance.web.redirect('https://accounts.odoo.com/web');
}); });
} }
}, },

View File

@ -923,6 +923,8 @@ instance.web.BufferedDataSet = instance.web.DataSetStatic.extend({
sign = -1; sign = -1;
field = field.slice(1); field = field.slice(1);
} }
if(!a[field] && a[field] !== 0){ return sign}
if(!b[field] && b[field] !== 0){ return (sign == -1) ? 1 : -1}
//m2o should be searched based on value[1] not based whole value(i.e. [id, value]) //m2o should be searched based on value[1] not based whole value(i.e. [id, value])
if(_.isArray(a[field]) && a[field].length == 2 && _.isString(a[field][1])){ if(_.isArray(a[field]) && a[field].length == 2 && _.isString(a[field][1])){
return sign * compare(a[field][1], b[field][1]); return sign * compare(a[field][1], b[field][1]);

View File

@ -24,7 +24,7 @@ from email.MIMEBase import MIMEBase
from email.MIMEMultipart import MIMEMultipart from email.MIMEMultipart import MIMEMultipart
from email.Charset import Charset from email.Charset import Charset
from email.Header import Header from email.Header import Header
from email.Utils import formatdate, make_msgid, COMMASPACE from email.Utils import formatdate, make_msgid, COMMASPACE, parseaddr
from email import Encoders from email import Encoders
import logging import logging
import re import re
@ -120,6 +120,7 @@ def encode_header_param(param_text):
return param_text_ascii if param_text_ascii\ return param_text_ascii if param_text_ascii\
else Charset('utf8').header_encode(param_text_utf8) else Charset('utf8').header_encode(param_text_utf8)
# TODO master, remove me, no longer used internaly
name_with_email_pattern = re.compile(r'("[^<@>]+")\s*<([^ ,<@]+@[^> ,]+)>') name_with_email_pattern = re.compile(r'("[^<@>]+")\s*<([^ ,<@]+@[^> ,]+)>')
address_pattern = re.compile(r'([^ ,<@]+@[^> ,]+)') address_pattern = re.compile(r'([^ ,<@]+@[^> ,]+)')
@ -143,15 +144,16 @@ def encode_rfc2822_address_header(header_text):
header_text_ascii = try_coerce_ascii(header_text_utf8) header_text_ascii = try_coerce_ascii(header_text_utf8)
if header_text_ascii: if header_text_ascii:
return header_text_ascii return header_text_ascii
name, email = parseaddr(header_text_utf8)
if not name:
return email
# non-ASCII characters are present, attempt to # non-ASCII characters are present, attempt to
# replace all "Name" patterns with the RFC2047- # replace all "Name" patterns with the RFC2047-
# encoded version # encoded version
def replace(match_obj): name_encoded = str(Header(name, 'utf-8'))
name, email = match_obj.group(1), match_obj.group(2) header_text_utf8 = "%s <%s>" % (name_encoded, email)
name_encoded = str(Header(name, 'utf-8'))
return "%s <%s>" % (name_encoded, email)
header_text_utf8 = name_with_email_pattern.sub(replace,
header_text_utf8)
# try again after encoding # try again after encoding
header_text_ascii = try_coerce_ascii(header_text_utf8) header_text_ascii = try_coerce_ascii(header_text_utf8)
if header_text_ascii: if header_text_ascii:

View File

@ -3699,6 +3699,7 @@ class BaseModel(object):
self.check_access_rights(cr, uid, 'unlink') self.check_access_rights(cr, uid, 'unlink')
ir_property = self.pool.get('ir.property') ir_property = self.pool.get('ir.property')
ir_attachment_obj = self.pool.get('ir.attachment')
# Check if the records are used as default properties. # Check if the records are used as default properties.
domain = [('res_id', '=', False), domain = [('res_id', '=', False),
@ -3737,6 +3738,13 @@ class BaseModel(object):
if ir_value_ids: if ir_value_ids:
ir_values_obj.unlink(cr, uid, ir_value_ids, context=context) ir_values_obj.unlink(cr, uid, ir_value_ids, context=context)
# For the same reason, removing the record relevant to ir_attachment
# The search is performed with sql as the search method of ir_attachment is overridden to hide attachments of deleted records
cr.execute('select id from ir_attachment where res_model = %s and res_id in %s', (self._name, sub_ids))
ir_attachment_ids = [ir_attachment[0] for ir_attachment in cr.fetchall()]
if ir_attachment_ids:
ir_attachment_obj.unlink(cr, uid, ir_attachment_ids, context=context)
for order, obj_name, store_ids, fields in result_store: for order, obj_name, store_ids, fields in result_store:
if obj_name == self._name: if obj_name == self._name:
effective_store_ids = list(set(store_ids) - set(ids)) effective_store_ids = list(set(store_ids) - set(ids))