diff --git a/addons/hr_expense/models/product_template.py b/addons/hr_expense/models/product_template.py
index 8b0d3057197..d6252889dfb 100644
--- a/addons/hr_expense/models/product_template.py
+++ b/addons/hr_expense/models/product_template.py
@@ -7,4 +7,5 @@ from openerp import fields, models
class ProductTemplate(models.Model):
_inherit = "product.template"
- can_be_expensed = fields.Boolean(help="Specify whether the product can be selected in an HR expense.")
+ can_be_expensed = fields.Boolean(help="Specify whether the product can be selected in an HR expense.", string="Can be Expensed")
+
diff --git a/addons/sale/res_config.py b/addons/sale/res_config.py
index cf30384d41c..e675ea343aa 100644
--- a/addons/sale/res_config.py
+++ b/addons/sale/res_config.py
@@ -71,8 +71,7 @@ class sale_configuration(osv.TransientModel):
'Advanced pricing based on formula: You can have all the rights on pricelist'),
'default_invoice_policy': fields.selection([
('order', 'Invoice ordered quantities'),
- ('delivery', 'Invoice delivered quantities'),
- ('cost', 'Invoice based on costs (time and material, expenses)')
+ ('delivery', 'Invoice delivered quantities')
], 'Default Invoicing', default_model='product.template'),
'deposit_product_id_setting': fields.many2one('product.product', 'Deposit Product',\
domain="[('type', '=', 'service')]",\
diff --git a/addons/sale/sale.py b/addons/sale/sale.py
index 7d5d4d484ec..13af8a676bb 100644
--- a/addons/sale/sale.py
+++ b/addons/sale/sale.py
@@ -449,11 +449,6 @@ class SaleOrder(models.Model):
if self.env.context.get('send_email'):
self.force_quotation_send()
order.order_line._action_procurement_create()
- if not order.project_id:
- for line in order.order_line:
- if line.product_id.invoice_policy == 'cost':
- order._create_analytic_account()
- break
if self.env['ir.values'].get_default('sale.config.settings', 'auto_done_setting'):
self.action_done()
return True
@@ -572,7 +567,7 @@ class SaleOrderLine(models.Model):
@api.depends('product_id.invoice_policy', 'order_id.state')
def _compute_qty_delivered_updateable(self):
for line in self:
- line.qty_delivered_updateable = line.product_id.invoice_policy in ('order', 'delivery') and line.order_id.state == 'sale' and line.product_id.track_service == 'manual'
+ line.qty_delivered_updateable = line.order_id.state == 'sale' and line.product_id.track_service == 'manual'
@api.depends('qty_invoiced', 'qty_delivered', 'product_uom_qty', 'order_id.state')
def _get_to_invoice_qty(self):
@@ -671,10 +666,6 @@ class SaleOrderLine(models.Model):
new_procs.run()
return new_procs
- @api.model
- def _get_analytic_invoice_policy(self):
- return ['cost']
-
@api.model
def _get_analytic_track_service(self):
return []
@@ -691,8 +682,7 @@ class SaleOrderLine(models.Model):
line = super(SaleOrderLine, self).create(values)
if line.state == 'sale':
if (not line.order_id.project_id and
- (line.product_id.track_service in self._get_analytic_track_service() or
- line.product_id.invoice_policy in self._get_analytic_invoice_policy())):
+ (line.product_id.track_service in self._get_analytic_track_service())):
line.order_id._create_analytic_account()
line._action_procurement_create()
@@ -1004,7 +994,10 @@ class ProductTemplate(models.Model):
default='manual')
sale_line_warn = fields.Selection(WARNING_MESSAGE, 'Sales Order Line', help=WARNING_HELP, required=True, default="no-message")
sale_line_warn_msg = fields.Text('Message for Sales Order Line')
-
+ expense_policy = fields.Selection(
+ [('no', 'No'), ('cost', 'At cost'), ('sales_price', 'At sale price')],
+ string='Re-Invoice Expenses',
+ default='no')
@api.multi
@api.depends('product_variant_ids.sales_count')
def _sales_count(self):
@@ -1033,8 +1026,6 @@ class ProductTemplate(models.Model):
invoice_policy = fields.Selection(
[('order', 'Ordered quantities'),
('delivery', 'Delivered quantities'),
- ('cost', 'Reinvoice Costs')],
- string='Invoicing Policy', help='Ordered Quantity: Invoice based on the quantity the customer ordered.\n'
- 'Delivered Quantity: Invoiced based on the quantity the vendor delivered.\n'
- 'Reinvoice Costs: Invoice with some additional charges (product transfer, labour charges,...)',
+ ], string='Invoicing Policy', help='Ordered Quantity: Invoice based on the quantity the customer ordered.\n'
+ 'Delivered Quantity: Invoiced based on the quantity the vendor delivered (time or deliveries).',
default='order')
diff --git a/addons/sale/sale_analytic.py b/addons/sale/sale_analytic.py
index 9261c5c4208..0eed9f4cf71 100644
--- a/addons/sale/sale_analytic.py
+++ b/addons/sale/sale_analytic.py
@@ -40,6 +40,13 @@ class AccountAnalyticLine(models.Model):
so_line = fields.Many2one('sale.order.line', string='Sale Order Line')
def _get_invoice_price(self, order):
+ if self.product_id.expense_policy == 'sales_price':
+ return self.product_id.with_context(
+ partner=order.partner_id.id,
+ date_order=order.date_order,
+ pricelist=order.pricelist_id.id,
+ uom=self.product_uom_id.id
+ ).price
if self.unit_amount == 0.0:
return 0.0
price_unit = abs(self.amount / self.unit_amount)
@@ -47,20 +54,12 @@ class AccountAnalyticLine(models.Model):
price_unit = self.currency_id.compute(price_unit, order.currency_id)
return price_unit
- def _get_sale_order_line_vals(self):
- order = self.env['sale.order'].search([('project_id', '=', self.account_id.id)], limit=1)
- if not order:
- return False
- if order.state != 'sale':
- raise UserError(_('The Sale Order %s linked to the Analytic Account must be validated before registering expenses.') % order.name)
-
+ def _get_sale_order_line_vals(self, order, price):
last_so_line = self.env['sale.order.line'].search([('order_id', '=', order.id)], order='sequence desc', limit=1)
last_sequence = last_so_line.sequence + 1 if last_so_line else 100
fpos = order.fiscal_position_id or order.partner_id.property_account_position_id
taxes = fpos.map_tax(self.product_id.taxes_id)
- price = self._get_invoice_price(order)
-
return {
'order_id': order.id,
'name': self.name,
@@ -77,30 +76,24 @@ class AccountAnalyticLine(models.Model):
def _get_sale_order_line(self, vals=None):
result = dict(vals or {})
so_line = result.get('so_line', False) or self.so_line
- if not so_line and self.account_id and self.product_id and self.product_id.invoice_policy in ('cost', 'order'):
+ if not so_line and self.account_id and self.product_id and (self.product_id.expense_policy!='no'):
+ order = self.env['sale.order'].search([('project_id', '=', self.account_id.id), ('state','=','sale')], limit=1)
+ if not order:
+ return result
+ price = self._get_invoice_price(order)
so_lines = self.env['sale.order.line'].search([
- ('order_id.project_id', '=', self.account_id.id),
- ('state', '=', 'sale'),
+ ('order_id', '=', order.id),
+ ('price_unit', '=', price),
('product_id', '=', self.product_id.id)])
- # Use the existing SO line only if the unit prices are the same, otherwise we create
- # a new line
- for line in so_lines:
- if line.product_id.invoice_policy != 'cost' or (line.product_id.invoice_policy == 'cost' and line.price_unit == self._get_invoice_price(line.order_id)):
- result.update({'so_line': line.id})
- so_line = line
- break
+ if so_lines:
+ result.update({'so_line': so_lines[0].id})
else:
- # This will trigger the creation of a new SO line
- so_line = False
-
- if not so_line and self.account_id and self.product_id and self.product_id.invoice_policy == 'cost':
- order_line_vals = self._get_sale_order_line_vals()
- if order_line_vals:
- so_line = self.env['sale.order.line'].create(order_line_vals)
- so_line._compute_tax_id()
- result.update({'so_line': so_line.id})
-
+ order_line_vals = self._get_sale_order_line_vals(order, price)
+ if order_line_vals:
+ so_line = self.env['sale.order.line'].create(order_line_vals)
+ so_line._compute_tax_id()
+ result.update({'so_line': so_line.id})
return result
@api.multi
diff --git a/addons/sale/sale_product_demo.xml b/addons/sale/sale_product_demo.xml
index c7287431017..a4b8c6a5b47 100644
--- a/addons/sale/sale_product_demo.xml
+++ b/addons/sale/sale_product_demo.xml
@@ -146,7 +146,7 @@
- cost
+ cost
diff --git a/addons/sale/tests/test_sale_order.py b/addons/sale/tests/test_sale_order.py
index af5ffecca9b..f920aaa10ca 100644
--- a/addons/sale/tests/test_sale_order.py
+++ b/addons/sale/tests/test_sale_order.py
@@ -40,7 +40,7 @@ class TestSaleOrder(TestSale):
# deliver lines except 'time and material' then invoice again
for line in so.order_line:
- line.qty_delivered = 2 if line.product_id.invoice_policy in ['order', 'delivery'] else 0
+ line.qty_delivered = 2 if line.product_id.expense_policy=='no' else 0
self.assertTrue(so.invoice_status == 'to invoice', 'Sale: SO status after delivery should be "to invoice"')
inv_id = so.action_invoice_create()
inv = inv_obj.browse(inv_id)
diff --git a/addons/sale_expense/__init__.py b/addons/sale_expense/__init__.py
index 48f417bbd93..67dee8c60db 100644
--- a/addons/sale_expense/__init__.py
+++ b/addons/sale_expense/__init__.py
@@ -1,3 +1,2 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-import models
diff --git a/addons/sale_expense/models/__init__.py b/addons/sale_expense/models/__init__.py
deleted file mode 100644
index 2bf570fe2be..00000000000
--- a/addons/sale_expense/models/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-import analytic
-import product
diff --git a/addons/sale_expense/models/analytic.py b/addons/sale_expense/models/analytic.py
deleted file mode 100644
index 3baeeaaa4f5..00000000000
--- a/addons/sale_expense/models/analytic.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from openerp import models
-
-
-class AccountAnalyticLine(models.Model):
- _inherit = "account.analytic.line"
-
- def _get_invoice_price(self, order):
- if self.product_id.invoice_policy == 'cost' and self.product_id.expense_policy == 'sales_price':
- return self.product_id.with_context(
- partner=order.partner_id.id,
- date_order=order.date_order,
- pricelist=order.pricelist_id.id,
- uom=self.product_uom_id.id
- ).price
- else:
- return super(AccountAnalyticLine, self)._get_invoice_price(order)
diff --git a/addons/sale_expense/models/product.py b/addons/sale_expense/models/product.py
deleted file mode 100644
index 0d3276b453f..00000000000
--- a/addons/sale_expense/models/product.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# -*- coding: utf-8 -*-
-# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
-from openerp import fields, models
-
-
-class ProductProduct(models.Model):
- _inherit = "product.template"
-
- expense_policy = fields.Selection(
- [('cost', 'At Cost'), ('sales_price', 'At Sales Price')],
- string='Expense Invoice Policy',
- help="If you invoice at cost, the expense will be invoiced on the sale order at the cost of the analytic line;"
- "if you invoice at sales price, the price of the product will be used instead.",
- default='cost')
diff --git a/addons/sale_expense/sale_expense_demo.xml b/addons/sale_expense/sale_expense_demo.xml
index ee398004c98..4aa55923c0d 100644
--- a/addons/sale_expense/sale_expense_demo.xml
+++ b/addons/sale_expense/sale_expense_demo.xml
@@ -1,19 +1,19 @@
-
+
- cost
+ delivery
sales_price
- cost
+ delivery
cost
- cost
+ delivery
cost
diff --git a/addons/sale_expense/views/product_view.xml b/addons/sale_expense/views/product_view.xml
index 5f2dbd81c0f..ddedc50e4dc 100644
--- a/addons/sale_expense/views/product_view.xml
+++ b/addons/sale_expense/views/product_view.xml
@@ -7,9 +7,8 @@
+ attrs="{'invisible': [('can_be_expensed','=',False)]}"/>
-
\ No newline at end of file
diff --git a/addons/sale_stock/sale_stock.py b/addons/sale_stock/sale_stock.py
index c8bdb407a72..70b6a7c8c11 100644
--- a/addons/sale_stock/sale_stock.py
+++ b/addons/sale_stock/sale_stock.py
@@ -285,7 +285,7 @@ class StockMove(models.Model):
# Update delivered quantities on sale order lines
todo = self.env['sale.order.line']
for move in self:
- if (move.procurement_id.sale_line_id) and (move.product_id.invoice_policy in ('order', 'delivery')):
+ if (move.procurement_id.sale_line_id) and (move.product_id.expense_policy=='no'):
todo |= move.procurement_id.sale_line_id
for line in todo:
line.qty_delivered = line._get_delivered_qty()
diff --git a/addons/sale_timesheet/models/sale_timesheet.py b/addons/sale_timesheet/models/sale_timesheet.py
index 4dfb0dda486..adf5a96deeb 100644
--- a/addons/sale_timesheet/models/sale_timesheet.py
+++ b/addons/sale_timesheet/models/sale_timesheet.py
@@ -33,7 +33,7 @@ class ProductTemplate(models.Model):
@api.onchange('type', 'invoice_policy')
def onchange_type_timesheet(self):
- if self.type == 'service' and self.invoice_policy != 'cost':
+ if self.type == 'service':
self.track_service = 'timesheet'
else:
self.track_service = 'manual'