[MERGE] [FORWARD] Forward port of saas-2 branch until revision 9036 (revid tde@openerp.com-20131209102019-kjeg0rx2au1d5e5v)
bzr revid: tde@openerp.com-20131209105031-17920wsidpqrwmxj
This commit is contained in:
commit
4b96e85a30
|
@ -28,7 +28,7 @@ import time
|
|||
import openerp
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp import tools
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.osv import fields, osv, expression
|
||||
from openerp.tools.translate import _
|
||||
from openerp.tools.float_utils import float_round
|
||||
|
||||
|
@ -579,15 +579,18 @@ class account_account(osv.osv):
|
|||
except:
|
||||
pass
|
||||
if name:
|
||||
ids = self.search(cr, user, [('code', '=like', name+"%")]+args, limit=limit)
|
||||
if not ids:
|
||||
ids = self.search(cr, user, [('shortcut', '=', name)]+ args, limit=limit)
|
||||
if not ids:
|
||||
ids = self.search(cr, user, [('name', operator, name)]+ args, limit=limit)
|
||||
if not ids and len(name.split()) >= 2:
|
||||
#Separating code and name of account for searching
|
||||
operand1,operand2 = name.split(' ',1) #name can contain spaces e.g. OpenERP S.A.
|
||||
ids = self.search(cr, user, [('code', operator, operand1), ('name', operator, operand2)]+ args, limit=limit)
|
||||
if operator not in expression.NEGATIVE_TERM_OPERATORS:
|
||||
ids = self.search(cr, user, ['|', ('code', '=like', name+"%"), '|', ('shortcut', '=', name), ('name', operator, name)]+args, limit=limit)
|
||||
if not ids and len(name.split()) >= 2:
|
||||
#Separating code and name of account for searching
|
||||
operand1,operand2 = name.split(' ',1) #name can contain spaces e.g. OpenERP S.A.
|
||||
ids = self.search(cr, user, [('code', operator, operand1), ('name', operator, operand2)]+ args, limit=limit)
|
||||
else:
|
||||
ids = self.search(cr, user, ['&','!', ('code', '=like', name+"%"), ('name', operator, name)]+args, limit=limit)
|
||||
# as negation want to restric, do if already have results
|
||||
if ids and len(name.split()) >= 2:
|
||||
operand1,operand2 = name.split(' ',1) #name can contain spaces e.g. OpenERP S.A.
|
||||
ids = self.search(cr, user, [('code', operator, operand1), ('name', operator, operand2), ('id', 'in', ids)]+ args, limit=limit)
|
||||
else:
|
||||
ids = self.search(cr, user, args, context=context, limit=limit)
|
||||
return self.name_get(cr, user, ids, context=context)
|
||||
|
@ -1573,11 +1576,6 @@ class account_move(osv.osv):
|
|||
obj_analytic_line = self.pool.get('account.analytic.line')
|
||||
obj_move_line = self.pool.get('account.move.line')
|
||||
for move in self.browse(cr, uid, ids, context):
|
||||
# Unlink old analytic lines on move_lines
|
||||
for obj_line in move.line_id:
|
||||
for obj in obj_line.analytic_lines:
|
||||
obj_analytic_line.unlink(cr,uid,obj.id)
|
||||
|
||||
journal = move.journal_id
|
||||
amount = 0
|
||||
line_ids = []
|
||||
|
|
|
@ -193,6 +193,8 @@ class account_move_line(osv.osv):
|
|||
if obj_line.analytic_account_id:
|
||||
if not obj_line.journal_id.analytic_journal_id:
|
||||
raise osv.except_osv(_('No Analytic Journal!'),_("You have to define an analytic journal on the '%s' journal!") % (obj_line.journal_id.name, ))
|
||||
if obj_line.analytic_lines:
|
||||
acc_ana_line_obj.unlink(cr,uid,[obj.id for obj in obj_line.analytic_lines])
|
||||
vals_line = self._prepare_analytic_line(cr, uid, obj_line, context=context)
|
||||
acc_ana_line_obj.create(cr, uid, vals_line)
|
||||
return True
|
||||
|
@ -1207,20 +1209,6 @@ class account_move_line(osv.osv):
|
|||
if not ok:
|
||||
raise osv.except_osv(_('Bad Account!'), _('You cannot use this general account in this journal, check the tab \'Entry Controls\' on the related journal.'))
|
||||
|
||||
if vals.get('analytic_account_id',False):
|
||||
if journal.analytic_journal_id:
|
||||
vals['analytic_lines'] = [(0,0, {
|
||||
'name': vals['name'],
|
||||
'date': vals.get('date', time.strftime('%Y-%m-%d')),
|
||||
'account_id': vals.get('analytic_account_id', False),
|
||||
'unit_amount': vals.get('quantity', 1.0),
|
||||
'amount': vals.get('debit', 0.0) or vals.get('credit', 0.0),
|
||||
'general_account_id': vals.get('account_id', False),
|
||||
'journal_id': journal.analytic_journal_id.id,
|
||||
'ref': vals.get('ref', False),
|
||||
'user_id': uid
|
||||
})]
|
||||
|
||||
result = super(account_move_line, self).create(cr, uid, vals, context=context)
|
||||
# CREATE Taxes
|
||||
if vals.get('account_tax_id', False):
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
from . import test_tax
|
||||
from . import test_search
|
||||
|
||||
fast_suite = [test_tax,
|
||||
]
|
||||
fast_suite = [
|
||||
test_tax,
|
||||
test_search,
|
||||
]
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
from openerp.tests.common import TransactionCase
|
||||
|
||||
class TestSearch(TransactionCase):
|
||||
"""Tests for search on name_search (account.account)
|
||||
|
||||
The name search on account.account is quite complexe, make sure
|
||||
we have all the correct results
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestSearch, self).setUp()
|
||||
cr, uid = self.cr, self.uid
|
||||
self.account_model = self.registry('account.account')
|
||||
self.account_type_model = self.registry('account.account.type')
|
||||
ac_ids = self.account_type_model.search(cr, uid, [], limit=1)
|
||||
self.atax = (int(self.account_model.create(cr, uid, dict(
|
||||
name="Tax Received",
|
||||
code="121",
|
||||
user_type=ac_ids[0],
|
||||
))), "121 Tax Received")
|
||||
|
||||
self.apurchase = (int(self.account_model.create(cr, uid, dict(
|
||||
name="Purchased Stocks",
|
||||
code="1101",
|
||||
user_type=ac_ids[0],
|
||||
))), "1101 Purchased Stocks")
|
||||
|
||||
self.asale = (int(self.account_model.create(cr, uid, dict(
|
||||
name="Product Sales",
|
||||
code="200",
|
||||
user_type=ac_ids[0],
|
||||
))), "200 Product Sales")
|
||||
|
||||
self.all_ids = [self.atax[0], self.apurchase[0], self.asale[0]]
|
||||
|
||||
def test_name_search(self):
|
||||
cr, uid = self.cr, self.uid
|
||||
atax_ids = self.account_model.name_search(cr, uid, name="Tax", operator='ilike', args=[('id', 'in', self.all_ids)])
|
||||
self.assertEqual(set([self.atax[0]]), set([a[0] for a in atax_ids]), "name_search 'ilike Tax' should have returned Tax Received account only")
|
||||
|
||||
atax_ids = self.account_model.name_search(cr, uid, name="Tax", operator='not ilike', args=[('id', 'in', self.all_ids)])
|
||||
self.assertEqual(set([self.apurchase[0], self.asale[0]]), set([a[0] for a in atax_ids]), "name_search 'not ilike Tax' should have returned all but Tax Received account")
|
||||
|
||||
apur_ids = self.account_model.name_search(cr, uid, name='1101', operator='ilike', args=[('id', 'in', self.all_ids)])
|
||||
self.assertEqual(set([self.apurchase[0]]), set([a[0] for a in apur_ids]), "name_search 'ilike 1101' should have returned Purchased Stocks account only")
|
||||
|
||||
apur_ids = self.account_model.name_search(cr, uid, name='1101', operator='not ilike', args=[('id', 'in', self.all_ids)])
|
||||
self.assertEqual(set([self.atax[0], self.asale[0]]), set([a[0] for a in apur_ids]), "name_search 'not ilike 1101' should have returned all but Purchased Stocks account")
|
||||
|
||||
asale_ids = self.account_model.name_search(cr, uid, name='200 Sales', operator='ilike', args=[('id', 'in', self.all_ids)])
|
||||
self.assertEqual(set([self.asale[0]]), set([a[0] for a in asale_ids]), "name_search 'ilike 200 Sales' should have returned Product Sales account only")
|
||||
|
||||
asale_ids = self.account_model.name_search(cr, uid, name='200 Sales', operator='not ilike', args=[('id', 'in', self.all_ids)])
|
||||
self.assertEqual(set([self.atax[0], self.apurchase[0]]), set([a[0] for a in asale_ids]), "name_search 'not ilike 200 Sales' should have returned all but Product Sales account")
|
||||
|
||||
asale_ids = self.account_model.name_search(cr, uid, name='Product Sales', operator='ilike', args=[('id', 'in', self.all_ids)])
|
||||
self.assertEqual(set([self.asale[0]]), set([a[0] for a in asale_ids]), "name_search 'ilike Product Sales' should have returned Product Sales account only")
|
||||
|
||||
asale_ids = self.account_model.name_search(cr, uid, name='Product Sales', operator='not ilike', args=[('id', 'in', self.all_ids)])
|
||||
self.assertEqual(set([self.atax[0], self.apurchase[0]]), set([a[0] for a in asale_ids]), "name_search 'not ilike Product Sales' should have returned all but Product Sales account")
|
|
@ -252,13 +252,10 @@ class mail_thread(osv.AbstractModel):
|
|||
new = set(command[2])
|
||||
|
||||
# remove partners that are no longer followers
|
||||
fol_ids = fol_obj.search(cr, SUPERUSER_ID,
|
||||
[('res_model', '=', self._name), ('res_id', '=', id), ('partner_id', 'not in', list(new))])
|
||||
fol_obj.unlink(cr, SUPERUSER_ID, fol_ids)
|
||||
self.message_unsubscribe(cr, uid, [id], list(old-new))
|
||||
|
||||
# add new followers
|
||||
for partner_id in new - old:
|
||||
fol_obj.create(cr, SUPERUSER_ID, {'res_model': self._name, 'res_id': id, 'partner_id': partner_id})
|
||||
self.message_subscribe(cr, uid, [id], list(new-old))
|
||||
|
||||
def _search_followers(self, cr, uid, obj, name, args, context):
|
||||
"""Search function for message_follower_ids
|
||||
|
@ -346,6 +343,7 @@ class mail_thread(osv.AbstractModel):
|
|||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
thread_id = super(mail_thread, self).create(cr, uid, values, context=context)
|
||||
|
||||
# automatic logging unless asked not to (mainly for various testing purpose)
|
||||
|
@ -355,6 +353,7 @@ class mail_thread(osv.AbstractModel):
|
|||
# subscribe uid unless asked not to
|
||||
if not context.get('mail_create_nosubscribe'):
|
||||
self.message_subscribe_users(cr, uid, [thread_id], [uid], context=context)
|
||||
|
||||
# auto_subscribe: take values and defaults into account
|
||||
create_values = dict(values)
|
||||
for key, val in context.iteritems():
|
||||
|
@ -1545,35 +1544,33 @@ class mail_thread(osv.AbstractModel):
|
|||
else:
|
||||
self.check_access_rights(cr, uid, 'write')
|
||||
|
||||
for record in self.browse(cr, SUPERUSER_ID, ids, context=context):
|
||||
existing_pids = set([f.id for f in record.message_follower_ids
|
||||
if f.id in partner_ids])
|
||||
existing_pids_dict = {}
|
||||
fol_ids = mail_followers_obj.search(cr, SUPERUSER_ID, [('res_model', '=', self._name), ('res_id', 'in', ids)])
|
||||
for fol in mail_followers_obj.browse(cr, SUPERUSER_ID, fol_ids, context=context):
|
||||
existing_pids_dict.setdefault(fol.res_id, set()).add(fol.partner_id.id)
|
||||
|
||||
# subtype_ids specified: update already subscribed partners
|
||||
if subtype_ids and fol_ids:
|
||||
mail_followers_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
|
||||
# subtype_ids not specified: do not update already subscribed partner, fetch default subtypes for new partners
|
||||
if subtype_ids is None:
|
||||
subtype_ids = subtype_obj.search(
|
||||
cr, uid, [
|
||||
('default', '=', True), '|', ('res_model', '=', self._name), ('res_model', '=', False)], context=context)
|
||||
|
||||
for id in ids:
|
||||
existing_pids = existing_pids_dict.get(id, set())
|
||||
new_pids = set(partner_ids) - existing_pids
|
||||
|
||||
# subtype_ids specified: update already subscribed partners
|
||||
if subtype_ids and existing_pids:
|
||||
fol_ids = mail_followers_obj.search(cr, SUPERUSER_ID, [
|
||||
('res_model', '=', self._name),
|
||||
('res_id', '=', record.id),
|
||||
('partner_id', 'in', list(existing_pids)),
|
||||
], context=context)
|
||||
mail_followers_obj.write(cr, SUPERUSER_ID, fol_ids, {'subtype_ids': [(6, 0, subtype_ids)]}, context=context)
|
||||
# subtype_ids not specified: do not update already subscribed partner, fetch default subtypes for new partners
|
||||
elif subtype_ids is None:
|
||||
subtype_ids = subtype_obj.search(cr, uid, [
|
||||
('default', '=', True),
|
||||
'|',
|
||||
('res_model', '=', self._name),
|
||||
('res_model', '=', False)
|
||||
], context=context)
|
||||
# subscribe new followers
|
||||
for new_pid in new_pids:
|
||||
mail_followers_obj.create(cr, SUPERUSER_ID, {
|
||||
'res_model': self._name,
|
||||
'res_id': record.id,
|
||||
'partner_id': new_pid,
|
||||
'subtype_ids': [(6, 0, subtype_ids)],
|
||||
}, context=context)
|
||||
mail_followers_obj.create(
|
||||
cr, SUPERUSER_ID, {
|
||||
'res_model': self._name,
|
||||
'res_id': id,
|
||||
'partner_id': new_pid,
|
||||
'subtype_ids': [(6, 0, subtype_ids)],
|
||||
}, context=context)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -1592,7 +1589,14 @@ class mail_thread(osv.AbstractModel):
|
|||
self.check_access_rights(cr, uid, 'read')
|
||||
else:
|
||||
self.check_access_rights(cr, uid, 'write')
|
||||
return self.write(cr, SUPERUSER_ID, ids, {'message_follower_ids': [(3, pid) for pid in partner_ids]}, context=context)
|
||||
fol_obj = self.pool['mail.followers']
|
||||
fol_ids = fol_obj.search(
|
||||
cr, SUPERUSER_ID, [
|
||||
('res_model', '=', self._name),
|
||||
('res_id', 'in', ids),
|
||||
('partner_id', 'in', partner_ids)
|
||||
], context=context)
|
||||
return fol_obj.unlink(cr, SUPERUSER_ID, fol_ids, context=context)
|
||||
|
||||
def _message_get_auto_subscribe_fields(self, cr, uid, updated_fields, auto_follow_fields=['user_id'], context=None):
|
||||
""" Returns the list of relational fields linking to res.users that should
|
||||
|
|
|
@ -915,8 +915,11 @@ class purchase_order_line(osv.osv):
|
|||
"""
|
||||
onchange handler of product_uom.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
if not uom_id:
|
||||
return {'value': {'price_unit': price_unit or 0.0, 'name': name or '', 'product_uom' : uom_id or False}}
|
||||
context = dict(context, purchase_uom_check=True)
|
||||
return self.onchange_product_id(cr, uid, ids, pricelist_id, product_id, qty, uom_id,
|
||||
partner_id, date_order=date_order, fiscal_position_id=fiscal_position_id, date_planned=date_planned,
|
||||
name=name, price_unit=price_unit, context=context)
|
||||
|
@ -990,7 +993,7 @@ class purchase_order_line(osv.osv):
|
|||
uom_id = product_uom_po_id
|
||||
|
||||
if product.uom_id.category_id.id != product_uom.browse(cr, uid, uom_id, context=context).category_id.id:
|
||||
if self._check_product_uom_group(cr, uid, context=context):
|
||||
if context.get('purchase_uom_check') and self._check_product_uom_group(cr, uid, context=context):
|
||||
res['warning'] = {'title': _('Warning!'), 'message': _('Selected Unit of Measure does not belong to the same category as the product Unit of Measure.')}
|
||||
uom_id = product_uom_po_id
|
||||
|
||||
|
|
|
@ -318,6 +318,9 @@ class sale_order(osv.osv):
|
|||
context = {}
|
||||
if vals.get('name', '/') == '/':
|
||||
vals['name'] = self.pool.get('ir.sequence').get(cr, uid, 'sale.order') or '/'
|
||||
if vals.get('partner_id') and any(f not in vals for f in ['partner_invoice_id', 'partner_shipping_id', 'pricelist_id']):
|
||||
defaults = self.onchange_partner_id(cr, uid, [], vals['partner_id'], context)['value']
|
||||
vals = dict(defaults, **vals)
|
||||
context.update({'mail_create_nolog': True})
|
||||
new_id = super(sale_order, self).create(cr, uid, vals, context=context)
|
||||
self.message_post(cr, uid, [new_id], body=_("Quotation created"), context=context)
|
||||
|
@ -831,6 +834,24 @@ class sale_order_line(osv.osv):
|
|||
pass
|
||||
return {'value': value}
|
||||
|
||||
def create(self, cr, uid, values, context=None):
|
||||
if values.get('order_id') and values.get('product_id') and any(f not in values for f in ['name', 'price_unit', 'type', 'product_uom_qty', 'product_uom']):
|
||||
order = self.pool['sale.order'].read(cr, uid, values['order_id'], ['pricelist_id', 'partner_id', 'date_order', 'fiscal_position'], context=context)
|
||||
defaults = self.product_id_change(cr, uid, [], order['pricelist_id'][0], values['product_id'],
|
||||
qty=float(values.get('product_uom_qty', False)),
|
||||
uom=values.get('product_uom', False),
|
||||
qty_uos=float(values.get('product_uos_qty', False)),
|
||||
uos=values.get('product_uos', False),
|
||||
name=values.get('name', False),
|
||||
partner_id=order['partner_id'][0],
|
||||
date_order=order['date_order'],
|
||||
fiscal_position=order['fiscal_position'][0] if order['fiscal_position'] else False,
|
||||
flag=False, # Force name update
|
||||
context=context
|
||||
)['value']
|
||||
values = dict(defaults, **values)
|
||||
return super(sale_order_line, self).create(cr, uid, values, context=context)
|
||||
|
||||
def copy_data(self, cr, uid, id, default=None, context=None):
|
||||
if not default:
|
||||
default = {}
|
||||
|
|
|
@ -47,7 +47,7 @@ class crm_make_sale(osv.osv_memory):
|
|||
return False
|
||||
|
||||
lead = lead_obj.read(cr, uid, active_id, ['partner_id'], context=context)
|
||||
return lead['partner_id'][0]
|
||||
return lead['partner_id'][0] if lead['partner_id'] else False
|
||||
|
||||
def view_init(self, cr, uid, fields_list, context=None):
|
||||
return super(crm_make_sale, self).view_init(cr, uid, fields_list, context=context)
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
<!-- Add menu: Billing - Deliveries to invoice -->
|
||||
<record id="outgoing_picking_list_to_invoice" model="ir.actions.act_window">
|
||||
<field name="name">Deliveries to Invoice</field>
|
||||
<field name="res_model">stock.picking</field>
|
||||
<field name="res_model">stock.picking.out</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form,calendar</field>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
</record>
|
||||
|
||||
|
||||
<act_window name="Create Invoice"
|
||||
<act_window name="Create Draft Invoices"
|
||||
res_model="stock.invoice.onshipping"
|
||||
src_model="stock.picking.out"
|
||||
key2="client_action_multi"
|
||||
|
|
Loading…
Reference in New Issue