[MERGE] forward port of branch saas-3 up to 21b1203
This commit is contained in:
commit
8e637bac92
|
@ -318,16 +318,26 @@ class account_invoice(models.Model):
|
||||||
@api.model
|
@api.model
|
||||||
def fields_view_get(self, view_id=None, view_type=False, toolbar=False, submenu=False):
|
def fields_view_get(self, view_id=None, view_type=False, toolbar=False, submenu=False):
|
||||||
context = self._context
|
context = self._context
|
||||||
|
|
||||||
|
def get_view_id(xid, name):
|
||||||
|
try:
|
||||||
|
return self.env['ir.model.data'].xmlid_to_res_id('account.' + xid, raise_if_not_found=True)
|
||||||
|
except ValueError:
|
||||||
|
try:
|
||||||
|
return self.env['ir.ui.view'].search([('name', '=', name)], limit=1).id
|
||||||
|
except Exception:
|
||||||
|
return False # view not found
|
||||||
|
|
||||||
if context.get('active_model') == 'res.partner' and context.get('active_ids'):
|
if context.get('active_model') == 'res.partner' and context.get('active_ids'):
|
||||||
partner = self.env['res.partner'].browse(context['active_ids'])[0]
|
partner = self.env['res.partner'].browse(context['active_ids'])[0]
|
||||||
if not view_type:
|
if not view_type:
|
||||||
view_id = self.env['ir.ui.view'].search([('name', '=', 'account.invoice.tree')]).id
|
view_id = get_view_id('invoice_tree', 'account.invoice.tree')
|
||||||
view_type = 'tree'
|
view_type = 'tree'
|
||||||
elif view_type == 'form':
|
elif view_type == 'form':
|
||||||
if partner.supplier and not partner.customer:
|
if partner.supplier and not partner.customer:
|
||||||
view_id = self.env['ir.ui.view'].search([('name', '=', 'account.invoice.supplier.form')]).id
|
view_id = get_view_id('invoice_supplier_form', 'account.invoice.supplier.form')
|
||||||
elif partner.customer and not partner.supplier:
|
elif partner.customer and not partner.supplier:
|
||||||
view_id = self.env['ir.ui.view'].search([('name', '=', 'account.invoice.form')]).id
|
view_id = get_view_id('invoice_form', 'account.invoice.form')
|
||||||
|
|
||||||
res = super(account_invoice, self).fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)
|
res = super(account_invoice, self).fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)
|
||||||
|
|
||||||
|
|
|
@ -33,10 +33,6 @@ class partner_balance(report_sxw.rml_parse, common_report_header):
|
||||||
self.account_ids = []
|
self.account_ids = []
|
||||||
self.localcontext.update( {
|
self.localcontext.update( {
|
||||||
'time': time,
|
'time': time,
|
||||||
'lines': self.lines,
|
|
||||||
'sum_debit': self._sum_debit,
|
|
||||||
'sum_credit': self._sum_credit,
|
|
||||||
'sum_litige': self._sum_litige,
|
|
||||||
'get_fiscalyear': self._get_fiscalyear,
|
'get_fiscalyear': self._get_fiscalyear,
|
||||||
'get_journal': self._get_journal,
|
'get_journal': self._get_journal,
|
||||||
'get_filter': self._get_filter,
|
'get_filter': self._get_filter,
|
||||||
|
@ -70,7 +66,20 @@ class partner_balance(report_sxw.rml_parse, common_report_header):
|
||||||
"WHERE a.type IN %s " \
|
"WHERE a.type IN %s " \
|
||||||
"AND a.active", (self.ACCOUNT_TYPE,))
|
"AND a.active", (self.ACCOUNT_TYPE,))
|
||||||
self.account_ids = [a for (a,) in self.cr.fetchall()]
|
self.account_ids = [a for (a,) in self.cr.fetchall()]
|
||||||
return super(partner_balance, self).set_context(objects, data, ids, report_type=report_type)
|
res = super(partner_balance, self).set_context(objects, data, ids, report_type=report_type)
|
||||||
|
lines = self.lines()
|
||||||
|
sum_debit = sum_credit = sum_litige = 0
|
||||||
|
for line in filter(lambda x: x['type'] == 3, lines):
|
||||||
|
sum_debit += line['debit'] or 0
|
||||||
|
sum_credit += line['credit'] or 0
|
||||||
|
sum_litige += line['enlitige'] or 0
|
||||||
|
self.localcontext.update({
|
||||||
|
'lines': lambda: lines,
|
||||||
|
'sum_debit': lambda: sum_debit,
|
||||||
|
'sum_credit': lambda: sum_credit,
|
||||||
|
'sum_litige': lambda: sum_litige,
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
|
||||||
def lines(self):
|
def lines(self):
|
||||||
move_state = ['draft','posted']
|
move_state = ['draft','posted']
|
||||||
|
@ -236,62 +245,6 @@ class partner_balance(report_sxw.rml_parse, common_report_header):
|
||||||
i = i + 1
|
i = i + 1
|
||||||
return completearray
|
return completearray
|
||||||
|
|
||||||
def _sum_debit(self):
|
|
||||||
move_state = ['draft','posted']
|
|
||||||
if self.target_move == 'posted':
|
|
||||||
move_state = ['posted']
|
|
||||||
|
|
||||||
if not self.ids:
|
|
||||||
return 0.0
|
|
||||||
self.cr.execute(
|
|
||||||
"SELECT sum(debit) " \
|
|
||||||
"FROM account_move_line AS l " \
|
|
||||||
"JOIN account_move am ON (am.id = l.move_id)" \
|
|
||||||
"WHERE l.account_id IN %s" \
|
|
||||||
"AND am.state IN %s" \
|
|
||||||
"AND " + self.query + "",
|
|
||||||
(tuple(self.account_ids), tuple(move_state)))
|
|
||||||
temp_res = float(self.cr.fetchone()[0] or 0.0)
|
|
||||||
return temp_res
|
|
||||||
|
|
||||||
def _sum_credit(self):
|
|
||||||
move_state = ['draft','posted']
|
|
||||||
if self.target_move == 'posted':
|
|
||||||
move_state = ['posted']
|
|
||||||
|
|
||||||
if not self.ids:
|
|
||||||
return 0.0
|
|
||||||
self.cr.execute(
|
|
||||||
"SELECT sum(credit) " \
|
|
||||||
"FROM account_move_line AS l " \
|
|
||||||
"JOIN account_move am ON (am.id = l.move_id)" \
|
|
||||||
"WHERE l.account_id IN %s" \
|
|
||||||
"AND am.state IN %s" \
|
|
||||||
"AND " + self.query + "",
|
|
||||||
(tuple(self.account_ids), tuple(move_state)))
|
|
||||||
temp_res = float(self.cr.fetchone()[0] or 0.0)
|
|
||||||
return temp_res
|
|
||||||
|
|
||||||
def _sum_litige(self):
|
|
||||||
#gives the total of move lines with blocked boolean set to TRUE for the report selection
|
|
||||||
move_state = ['draft','posted']
|
|
||||||
if self.target_move == 'posted':
|
|
||||||
move_state = ['posted']
|
|
||||||
|
|
||||||
if not self.ids:
|
|
||||||
return 0.0
|
|
||||||
self.cr.execute(
|
|
||||||
"SELECT sum(debit-credit) " \
|
|
||||||
"FROM account_move_line AS l " \
|
|
||||||
"JOIN account_move am ON (am.id = l.move_id)" \
|
|
||||||
"WHERE l.account_id IN %s" \
|
|
||||||
"AND am.state IN %s" \
|
|
||||||
"AND " + self.query + " " \
|
|
||||||
"AND l.blocked=TRUE ",
|
|
||||||
(tuple(self.account_ids), tuple(move_state), ))
|
|
||||||
temp_res = float(self.cr.fetchone()[0] or 0.0)
|
|
||||||
return temp_res
|
|
||||||
|
|
||||||
def _get_partners(self):
|
def _get_partners(self):
|
||||||
|
|
||||||
if self.result_selection == 'customer':
|
if self.result_selection == 'customer':
|
||||||
|
|
|
@ -39,13 +39,15 @@ class account_analytic_profit(report_sxw.rml_parse):
|
||||||
return user_obj.browse(self.cr, self.uid, ids)
|
return user_obj.browse(self.cr, self.uid, ids)
|
||||||
|
|
||||||
def _journal_ids(self, form, user_id):
|
def _journal_ids(self, form, user_id):
|
||||||
|
if isinstance(user_id, (int, long)):
|
||||||
|
user_id = [user_id]
|
||||||
line_obj = self.pool['account.analytic.line']
|
line_obj = self.pool['account.analytic.line']
|
||||||
journal_obj = self.pool['account.analytic.journal']
|
journal_obj = self.pool['account.analytic.journal']
|
||||||
line_ids=line_obj.search(self.cr, self.uid, [
|
line_ids=line_obj.search(self.cr, self.uid, [
|
||||||
('date', '>=', form['date_from']),
|
('date', '>=', form['date_from']),
|
||||||
('date', '<=', form['date_to']),
|
('date', '<=', form['date_to']),
|
||||||
('journal_id', 'in', form['journal_ids'][0][2]),
|
('journal_id', 'in', form['journal_ids'][0][2]),
|
||||||
('user_id', '=', user_id),
|
('user_id', 'in', user_id),
|
||||||
])
|
])
|
||||||
ids=list(set([b.journal_id.id for b in line_obj.browse(self.cr, self.uid, line_ids)]))
|
ids=list(set([b.journal_id.id for b in line_obj.browse(self.cr, self.uid, line_ids)]))
|
||||||
return journal_obj.browse(self.cr, self.uid, ids)
|
return journal_obj.browse(self.cr, self.uid, ids)
|
||||||
|
|
|
@ -315,7 +315,12 @@ class product_pricelist(osv.osv):
|
||||||
price = price * (1.0+(rule.price_discount or 0.0))
|
price = price * (1.0+(rule.price_discount or 0.0))
|
||||||
if rule.price_round:
|
if rule.price_round:
|
||||||
price = tools.float_round(price, precision_rounding=rule.price_round)
|
price = tools.float_round(price, precision_rounding=rule.price_round)
|
||||||
price += (rule.price_surcharge or 0.0)
|
if context.get('uom'):
|
||||||
|
# compute price_surcharge based on reference uom
|
||||||
|
factor = product_uom_obj.browse(cr, uid, context.get('uom'), context=context).factor
|
||||||
|
else:
|
||||||
|
factor = 1.0
|
||||||
|
price += (rule.price_surcharge or 0.0) / factor
|
||||||
if rule.price_min_margin:
|
if rule.price_min_margin:
|
||||||
price = max(price, price_limit+rule.price_min_margin)
|
price = max(price, price_limit+rule.price_min_margin)
|
||||||
if rule.price_max_margin:
|
if rule.price_max_margin:
|
||||||
|
|
|
@ -1118,6 +1118,34 @@ class product_product(osv.osv):
|
||||||
def need_procurement(self, cr, uid, ids, context=None):
|
def need_procurement(self, cr, uid, ids, context=None):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _compute_uos_qty(self, cr, uid, ids, uom, qty, uos, context=None):
|
||||||
|
'''
|
||||||
|
Computes product's invoicing quantity in UoS from quantity in UoM.
|
||||||
|
Takes into account the
|
||||||
|
:param uom: Source unit
|
||||||
|
:param qty: Source quantity
|
||||||
|
:param uos: Target UoS unit.
|
||||||
|
'''
|
||||||
|
if not uom or not qty or not uos:
|
||||||
|
return qty
|
||||||
|
uom_obj = self.pool['product.uom']
|
||||||
|
product_id = ids[0] if isinstance(ids, (list, tuple)) else ids
|
||||||
|
product = self.browse(cr, uid, product_id, context=context)
|
||||||
|
if isinstance(uos, (int, long)):
|
||||||
|
uos = uom_obj.browse(cr, uid, uos, context=context)
|
||||||
|
if isinstance(uom, (int, long)):
|
||||||
|
uom = uom_obj.browse(cr, uid, uom, context=context)
|
||||||
|
if product.uos_id: # Product has UoS defined
|
||||||
|
# We cannot convert directly between units even if the units are of the same category
|
||||||
|
# as we need to apply the conversion coefficient which is valid only between quantities
|
||||||
|
# in product's default UoM/UoS
|
||||||
|
qty_default_uom = uom_obj._compute_qty_obj(cr, uid, uom, qty, product.uom_id) # qty in product's default UoM
|
||||||
|
qty_default_uos = qty_default_uom * product.uos_coeff
|
||||||
|
return uom_obj._compute_qty_obj(cr, uid, product.uos_id, qty_default_uos, uos)
|
||||||
|
else:
|
||||||
|
return uom_obj._compute_qty_obj(cr, uid, uom, qty, uos)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class product_packaging(osv.osv):
|
class product_packaging(osv.osv):
|
||||||
_name = "product.packaging"
|
_name = "product.packaging"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from . import test_uom
|
from . import test_uom, test_pricelist
|
||||||
|
|
||||||
fast_suite = [
|
fast_suite = [
|
||||||
test_uom,
|
test_uom,
|
||||||
|
test_pricelist
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
from openerp.tests.common import TransactionCase
|
||||||
|
|
||||||
|
class TestPricelist(TransactionCase):
|
||||||
|
"""Tests for unit of measure conversion"""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestPricelist, self).setUp()
|
||||||
|
cr, uid, context = self.cr, self.uid, {}
|
||||||
|
self.ir_model_data = self.registry('ir.model.data')
|
||||||
|
self.product_product = self.registry('product.product')
|
||||||
|
self.product_pricelist = self.registry('product.pricelist')
|
||||||
|
self.uom = self.registry('product.uom')
|
||||||
|
|
||||||
|
self.usb_adapter_id = self.ir_model_data.get_object_reference(cr, uid, 'product', 'product_product_48')[1]
|
||||||
|
self.datacard_id = self.ir_model_data.get_object_reference(cr, uid, 'product', 'product_product_46')[1]
|
||||||
|
self.unit_id = self.ir_model_data.get_object_reference(cr, uid, 'product', 'product_uom_unit')[1]
|
||||||
|
self.dozen_id = self.ir_model_data.get_object_reference(cr, uid, 'product', 'product_uom_dozen')[1]
|
||||||
|
|
||||||
|
self.public_pricelist_id = self.ir_model_data.get_object_reference(cr, uid, 'product', 'list0')[1]
|
||||||
|
self.sale_pricelist_id = self.product_pricelist.create(cr, uid, {
|
||||||
|
'name': 'Sale pricelist',
|
||||||
|
'type': 'sale',
|
||||||
|
'version_id': [(0, 0, {
|
||||||
|
'name': 'v1.0',
|
||||||
|
'items_id': [(0, 0, {
|
||||||
|
'name': 'Discount 10%',
|
||||||
|
'base': 1, # based on public price
|
||||||
|
'price_discount': -0.1,
|
||||||
|
'product_id': self.usb_adapter_id
|
||||||
|
}), (0, 0, {
|
||||||
|
'name': 'Discount -0.5',
|
||||||
|
'base': 1, # based on public price
|
||||||
|
'price_surcharge': -0.5,
|
||||||
|
'product_id': self.datacard_id
|
||||||
|
})]
|
||||||
|
})]
|
||||||
|
}, context=context)
|
||||||
|
|
||||||
|
def test_10_discount(self):
|
||||||
|
# Make sure the price using a pricelist is the same than without after
|
||||||
|
# applying the computation manually
|
||||||
|
cr, uid, context = self.cr, self.uid, {}
|
||||||
|
|
||||||
|
public_context = dict(context, pricelist=self.public_pricelist_id)
|
||||||
|
pricelist_context = dict(context, pricelist=self.sale_pricelist_id)
|
||||||
|
|
||||||
|
usb_adapter_without_pricelist = self.product_product.browse(cr, uid, self.usb_adapter_id, context=public_context)
|
||||||
|
usb_adapter_with_pricelist = self.product_product.browse(cr, uid, self.usb_adapter_id, context=pricelist_context)
|
||||||
|
self.assertEqual(usb_adapter_with_pricelist.price, usb_adapter_without_pricelist.price*0.9)
|
||||||
|
|
||||||
|
datacard_without_pricelist = self.product_product.browse(cr, uid, self.datacard_id, context=public_context)
|
||||||
|
datacard_with_pricelist = self.product_product.browse(cr, uid, self.datacard_id, context=pricelist_context)
|
||||||
|
self.assertEqual(datacard_with_pricelist.price, datacard_without_pricelist.price-0.5)
|
||||||
|
|
||||||
|
# Make sure that changing the unit of measure does not break the unit
|
||||||
|
# price (after converting)
|
||||||
|
unit_context = dict(context,
|
||||||
|
pricelist=self.sale_pricelist_id,
|
||||||
|
uom=self.unit_id)
|
||||||
|
dozen_context = dict(context,
|
||||||
|
pricelist=self.sale_pricelist_id,
|
||||||
|
uom=self.dozen_id)
|
||||||
|
|
||||||
|
usb_adapter_unit = self.product_product.browse(cr, uid, self.usb_adapter_id, context=unit_context)
|
||||||
|
usb_adapter_dozen = self.product_product.browse(cr, uid, self.usb_adapter_id, context=dozen_context)
|
||||||
|
self.assertAlmostEqual(usb_adapter_unit.price*12, usb_adapter_dozen.price)
|
||||||
|
|
||||||
|
datacard_unit = self.product_product.browse(cr, uid, self.datacard_id, context=unit_context)
|
||||||
|
datacard_dozen = self.product_product.browse(cr, uid, self.datacard_id, context=dozen_context)
|
||||||
|
self.assertAlmostEqual(datacard_unit.price*12, datacard_dozen.price)
|
|
@ -43,6 +43,7 @@ class sale_order_line(osv.osv):
|
||||||
fiscal_position=False, flag=False, context=None):
|
fiscal_position=False, flag=False, context=None):
|
||||||
|
|
||||||
def get_real_price(res_dict, product_id, qty, uom, pricelist):
|
def get_real_price(res_dict, product_id, qty, uom, pricelist):
|
||||||
|
"""Retrieve the price before applying the pricelist"""
|
||||||
item_obj = self.pool.get('product.pricelist.item')
|
item_obj = self.pool.get('product.pricelist.item')
|
||||||
price_type_obj = self.pool.get('product.price.type')
|
price_type_obj = self.pool.get('product.price.type')
|
||||||
product_obj = self.pool.get('product.product')
|
product_obj = self.pool.get('product.product')
|
||||||
|
@ -58,9 +59,8 @@ class sale_order_line(osv.osv):
|
||||||
|
|
||||||
factor = 1.0
|
factor = 1.0
|
||||||
if uom and uom != product.uom_id.id:
|
if uom and uom != product.uom_id.id:
|
||||||
product_uom_obj = self.pool.get('product.uom')
|
# the unit price is in a different uom
|
||||||
uom_data = product_uom_obj.browse(cr, uid, product.uom_id.id)
|
factor = self.pool['product.uom']._compute_qty(cr, uid, uom, 1.0, product.uom_id.id)
|
||||||
factor = uom_data.factor
|
|
||||||
return product_read[field_name] * factor
|
return product_read[field_name] * factor
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ class sale_order_line(osv.osv):
|
||||||
price=result['price_unit']
|
price=result['price_unit']
|
||||||
else:
|
else:
|
||||||
return res
|
return res
|
||||||
|
uom = result.get('product_uom', uom)
|
||||||
product = product_obj.browse(cr, uid, product, context)
|
product = product_obj.browse(cr, uid, product, context)
|
||||||
pricelist_context = dict(context, uom=uom, date=date_order)
|
pricelist_context = dict(context, uom=uom, date=date_order)
|
||||||
list_price = pricelist_obj.price_rule_get(cr, uid, [pricelist],
|
list_price = pricelist_obj.price_rule_get(cr, uid, [pricelist],
|
||||||
|
|
|
@ -101,7 +101,8 @@ class sale_order_line_make_invoice(osv.osv_memory):
|
||||||
flag = False
|
flag = False
|
||||||
break
|
break
|
||||||
if flag:
|
if flag:
|
||||||
workflow.trg_validate(uid, 'sale.order', order.id, 'manual_invoice', cr)
|
line.order_id.write({'state': 'progress'})
|
||||||
|
workflow.trg_validate(uid, 'sale.order', order.id, 'all_lines', cr)
|
||||||
|
|
||||||
if not invoices:
|
if not invoices:
|
||||||
raise osv.except_osv(_('Warning!'), _('Invoice cannot be created for this Sales Order Line due to one of the following reasons:\n1.The state of this sales order line is either "draft" or "cancel"!\n2.The Sales Order Line is Invoiced!'))
|
raise osv.except_osv(_('Warning!'), _('Invoice cannot be created for this Sales Order Line due to one of the following reasons:\n1.The state of this sales order line is either "draft" or "cancel"!\n2.The Sales Order Line is Invoiced!'))
|
||||||
|
|
|
@ -36,7 +36,11 @@ class sale_order_line(osv.osv):
|
||||||
frm_cur = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id
|
frm_cur = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_id.id
|
||||||
to_cur = self.pool.get('product.pricelist').browse(cr, uid, [pricelist])[0].currency_id.id
|
to_cur = self.pool.get('product.pricelist').browse(cr, uid, [pricelist])[0].currency_id.id
|
||||||
if product:
|
if product:
|
||||||
purchase_price = self.pool.get('product.product').browse(cr, uid, product).standard_price
|
product = self.pool['product.product'].browse(cr, uid, product, context=context)
|
||||||
|
purchase_price = product.standard_price
|
||||||
|
to_uom = res.get('product_uom', uom)
|
||||||
|
if to_uom != product.uom_id.id:
|
||||||
|
purchase_price = self.pool['product.uom']._compute_price(cr, uid, product.uom_id.id, purchase_price, to_uom)
|
||||||
ctx = context.copy()
|
ctx = context.copy()
|
||||||
ctx['date'] = date_order
|
ctx['date'] = date_order
|
||||||
price = self.pool.get('res.currency').compute(cr, uid, frm_cur, to_cur, purchase_price, round=False, context=ctx)
|
price = self.pool.get('res.currency').compute(cr, uid, frm_cur, to_cur, purchase_price, round=False, context=ctx)
|
||||||
|
|
|
@ -820,7 +820,7 @@ openerp.web_calendar = function(instance) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var pop = new instance.web.form.FormOpenPopup(this);
|
var pop = new instance.web.form.FormOpenPopup(this);
|
||||||
pop.show_element(this.dataset.model, id, this.dataset.get_context(), {
|
pop.show_element(this.dataset.model, parseInt(id), this.dataset.get_context(), {
|
||||||
title: _.str.sprintf(_t("View: %s"),title),
|
title: _.str.sprintf(_t("View: %s"),title),
|
||||||
view_id: +this.open_popup_action,
|
view_id: +this.open_popup_action,
|
||||||
res_id: id,
|
res_id: id,
|
||||||
|
|
Loading…
Reference in New Issue