Merge lp:~borjals/openobject-addons/extra-5.0-bugfix-603100 into lp:openobject-addons/extra-5.0

Proposed by Borja López Soilán (NeoPolus)
Status: Merged
Merged at revision: 4462
Proposed branch: lp:~borjals/openobject-addons/extra-5.0-bugfix-603100
Merge into: lp:openobject-addons/extra-5.0
Diff against target: 731 lines (+515/-107)
7 files modified
purchase_tax_include/__init__.py (+15/-11)
purchase_tax_include/__terp__.py (+10/-11)
purchase_tax_include/i18n/es_ES.po (+89/-0)
purchase_tax_include/i18n/fr_BE.po (+52/-0)
purchase_tax_include/i18n/purchase_tax_include.pot (+89/-0)
purchase_tax_include/purchase_tax_incl.py (+220/-57)
purchase_tax_include/purchase_tax_incl.xml (+40/-28)
To merge this branch: bzr merge lp:~borjals/openobject-addons/extra-5.0-bugfix-603100
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+29567@code.launchpad.net

Description of the change

Complete rewrite of the purchase_tax_include module to address multiple bugs.

- Solved "column 'amount_tax' of relation 'purchase_order' does not exist"
  error when saving a purchase order (bug 603100).
  The previous fields redefinitions where incompatible with the purchase
  module from the 5.0 addons since Dec 2008.

- Now correct 'amount_untaxed' and 'amount_total' are shown on the
  purchase order totals.

- Now 'price_subtotal_incl' column is properly displayed on the
  purchase order lines list of the purchase form.

- When the order is invoiced, the created invoice did not use the
  price type of the order, so the amounts didn't match; fixed.

- When a picking is invoiced, the created invoice did not use the
  price type of the original orders; fixed.

To post a comment you must log in.
Revision history for this message
Borja López Soilán (NeoPolus) (borjals) wrote :

Ok, this has been waiting for a month and only Numérigraphe (thanks!) reviewed the merge proposal (on trunk). As in its current state purchase_tax_include is not usable at all, I think I'll just merge it tomorrow.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'purchase_tax_include/__init__.py'
--- purchase_tax_include/__init__.py 2008-11-03 19:56:05 +0000
+++ purchase_tax_include/__init__.py 2010-07-09 15:01:37 +0000
@@ -1,25 +1,29 @@
1# -*- encoding: utf-8 -*-1# -*- encoding: utf-8 -*-
2##############################################################################2##############################################################################
3#3#
4# OpenERP, Open Source Management Solution 4# OpenERP, Open Source Management Solution
5# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved5# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
6# $Id$
7#6#
8# This program is free software: you can redistribute it and/or modify7# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by8# it under the terms of the GNU Affero General Public License as
10# the Free Software Foundation, either version 3 of the License, or9# published by the Free Software Foundation, either version 3 of the
11# (at your option) any later version.10# License, or (at your option) any later version.
12#11#
13# This program is distributed in the hope that it will be useful,12# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of13# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.15# GNU Affero General Public License for more details.
17#16#
18# You should have received a copy of the GNU General Public License17# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.18# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#19#
21##############################################################################20##############################################################################
2221
22__authors__ = [
23 "OpenERP S.A.",
24 "Borja López Soilán (Pexego) <borjals@pexego.es>"
25]
26
23import purchase_tax_incl27import purchase_tax_incl
24# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:28
2529
2630
=== modified file 'purchase_tax_include/__terp__.py'
--- purchase_tax_include/__terp__.py 2009-02-17 12:57:51 +0000
+++ purchase_tax_include/__terp__.py 2010-07-09 15:01:37 +0000
@@ -1,27 +1,26 @@
1# -*- encoding: utf-8 -*-1# -*- encoding: utf-8 -*-
2##############################################################################2##############################################################################
3#3#
4# OpenERP, Open Source Management Solution 4# OpenERP, Open Source Management Solution
5# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved5# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
6# $Id$
7#6#
8# This program is free software: you can redistribute it and/or modify7# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by8# it under the terms of the GNU Affero General Public License as
10# the Free Software Foundation, either version 3 of the License, or9# published by the Free Software Foundation, either version 3 of the
11# (at your option) any later version.10# License, or (at your option) any later version.
12#11#
13# This program is distributed in the hope that it will be useful,12# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of13# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.15# GNU Affero General Public License for more details.
17#16#
18# You should have received a copy of the GNU General Public License17# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.18# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#19#
21##############################################################################20##############################################################################
22{21{
23 "name" : "Purchases with taxes included",22 "name" : "Purchases with taxes included",
24 "version" : "1.0",23 "version" : "2.0",
25 "depends" : ["purchase","account_tax_include"],24 "depends" : ["purchase","account_tax_include"],
26 "author" : "Tiny",25 "author" : "Tiny",
27 "website" : "http://www.openerp.com",26 "website" : "http://www.openerp.com",
2827
=== added directory 'purchase_tax_include/i18n'
=== added file 'purchase_tax_include/i18n/es_ES.po'
--- purchase_tax_include/i18n/es_ES.po 1970-01-01 00:00:00 +0000
+++ purchase_tax_include/i18n/es_ES.po 2010-07-09 15:01:37 +0000
@@ -0,0 +1,89 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * purchase_tax_include
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 6.0dev\n"
8"Report-Msgid-Bugs-To: support@openerp.com\n"
9"POT-Creation-Date: 2010-07-09 11:24:53+0000\n"
10"PO-Revision-Date: 2010-07-09 13:32+0100\n"
11"Last-Translator: Borja López Soilán (Pexego) <borjals@pexego.es>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: 8bit\n"
16"Plural-Forms: \n"
17
18#. module: purchase_tax_include
19#: constraint:ir.ui.view:0
20msgid "Invalid XML for View Architecture!"
21msgstr "¡XML inválido para la definición de la vista!"
22
23#. module: purchase_tax_include
24#: constraint:ir.model:0
25msgid "The Object name must start with x_ and not contain any special character !"
26msgstr "¡El nombre del objeto debe empezar con x_ y no contener ningún carácter especial!"
27
28#. module: purchase_tax_include
29#: code:addons/purchase_tax_include/purchase_tax_incl.py:0
30#, python-format
31msgid "You can't mix tax included and tax excluded purchases in one invoice!"
32msgstr "¡No puede mezclar compras con impuestos incluidos y excluidos en una factura!"
33
34#. module: purchase_tax_include
35#: field:purchase.order,price_type:0
36msgid "Price method"
37msgstr "Método de precio"
38
39#. module: purchase_tax_include
40#: model:ir.module.module,shortdesc:purchase_tax_include.module_meta_information
41msgid "Purchases with taxes included"
42msgstr "Compras con impuestos incluidos"
43
44#. module: purchase_tax_include
45#: selection:purchase.order,price_type:0
46msgid "Tax included"
47msgstr "Impuestos incluidos"
48
49#. module: purchase_tax_include
50#: model:ir.model,name:purchase_tax_include.model_purchase_order
51msgid "Purchase order"
52msgstr "Pedido de compra"
53
54#. module: purchase_tax_include
55#: code:addons/purchase_tax_include/purchase_tax_incl.py:0
56#, python-format
57msgid "Error!"
58msgstr "¡Error!"
59
60#. module: purchase_tax_include
61#: selection:purchase.order,price_type:0
62msgid "Tax excluded"
63msgstr "Impuestos excluidos"
64
65#. module: purchase_tax_include
66#: model:ir.model,name:purchase_tax_include.model_purchase_order_line
67msgid "Purchase Order lines"
68msgstr "Líneas del pedido de compra"
69
70#. module: purchase_tax_include
71#: model:ir.module.module,description:purchase_tax_include.module_meta_information
72msgid "This module allows you to use purchase order with prices including or excluding taxes."
73msgstr "Este módulo le permite usar órdenes de compra con precios con impuestos incluídos o excluidos."
74
75#. module: purchase_tax_include
76#: model:ir.model,name:purchase_tax_include.model_stock_picking
77msgid "Picking List"
78msgstr "Albarán"
79
80#. module: purchase_tax_include
81#: field:purchase.order.line,price_subtotal:0
82msgid "Subtotal w/o tax"
83msgstr "Subtotal sin imp."
84
85#. module: purchase_tax_include
86#: field:purchase.order.line,price_subtotal_incl:0
87msgid "Subtotal"
88msgstr "Subtotal"
89
090
=== added file 'purchase_tax_include/i18n/fr_BE.po'
--- purchase_tax_include/i18n/fr_BE.po 1970-01-01 00:00:00 +0000
+++ purchase_tax_include/i18n/fr_BE.po 2010-07-09 15:01:37 +0000
@@ -0,0 +1,52 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * purchase_tax_include
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 5.0.6\n"
8"Report-Msgid-Bugs-To: support@openerp.com\n"
9"POT-Creation-Date: 2009-11-25 14:07:16+0000\n"
10"PO-Revision-Date: 2009-11-25 14:07:16+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: purchase_tax_include
19#: constraint:ir.ui.view:0
20msgid "Invalid XML for View Architecture!"
21msgstr ""
22
23#. module: purchase_tax_include
24#: field:purchase.order,price_type:0
25msgid "Price method"
26msgstr ""
27
28#. module: purchase_tax_include
29#: model:ir.module.module,shortdesc:purchase_tax_include.module_meta_information
30msgid "Purchases with taxes included"
31msgstr ""
32
33#. module: purchase_tax_include
34#: selection:purchase.order,price_type:0
35msgid "Tax included"
36msgstr ""
37
38#. module: purchase_tax_include
39#: selection:purchase.order,price_type:0
40msgid "Tax excluded"
41msgstr ""
42
43#. module: purchase_tax_include
44#: model:ir.module.module,description:purchase_tax_include.module_meta_information
45msgid "This module allows you to use purchase order with prices including or excluding taxes."
46msgstr ""
47
48#. module: purchase_tax_include
49#: field:purchase.order.line,price_subtotal_incl:0
50msgid "Subtotal"
51msgstr ""
52
053
=== added file 'purchase_tax_include/i18n/purchase_tax_include.pot'
--- purchase_tax_include/i18n/purchase_tax_include.pot 1970-01-01 00:00:00 +0000
+++ purchase_tax_include/i18n/purchase_tax_include.pot 2010-07-09 15:01:37 +0000
@@ -0,0 +1,89 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * purchase_tax_include
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 6.0dev\n"
8"Report-Msgid-Bugs-To: support@openerp.com\n"
9"POT-Creation-Date: 2010-07-09 11:22:17+0000\n"
10"PO-Revision-Date: 2010-07-09 11:22:17+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: purchase_tax_include
19#: constraint:ir.ui.view:0
20msgid "Invalid XML for View Architecture!"
21msgstr ""
22
23#. module: purchase_tax_include
24#: constraint:ir.model:0
25msgid "The Object name must start with x_ and not contain any special character !"
26msgstr ""
27
28#. module: purchase_tax_include
29#: code:addons/purchase_tax_include/purchase_tax_incl.py:0
30#, python-format
31msgid "You can't mix tax included and tax excluded purchases in one invoice!"
32msgstr ""
33
34#. module: purchase_tax_include
35#: field:purchase.order,price_type:0
36msgid "Price method"
37msgstr ""
38
39#. module: purchase_tax_include
40#: model:ir.module.module,shortdesc:purchase_tax_include.module_meta_information
41msgid "Purchases with taxes included"
42msgstr ""
43
44#. module: purchase_tax_include
45#: selection:purchase.order,price_type:0
46msgid "Tax included"
47msgstr ""
48
49#. module: purchase_tax_include
50#: model:ir.model,name:purchase_tax_include.model_purchase_order
51msgid "Purchase order"
52msgstr ""
53
54#. module: purchase_tax_include
55#: code:addons/purchase_tax_include/purchase_tax_incl.py:0
56#, python-format
57msgid "Error!"
58msgstr ""
59
60#. module: purchase_tax_include
61#: selection:purchase.order,price_type:0
62msgid "Tax excluded"
63msgstr ""
64
65#. module: purchase_tax_include
66#: model:ir.model,name:purchase_tax_include.model_purchase_order_line
67msgid "Purchase Order lines"
68msgstr ""
69
70#. module: purchase_tax_include
71#: model:ir.module.module,description:purchase_tax_include.module_meta_information
72msgid "This module allows you to use purchase order with prices including or excluding taxes."
73msgstr ""
74
75#. module: purchase_tax_include
76#: model:ir.model,name:purchase_tax_include.model_stock_picking
77msgid "Picking List"
78msgstr ""
79
80#. module: purchase_tax_include
81#: field:purchase.order.line,price_subtotal:0
82msgid "Subtotal w/o tax"
83msgstr ""
84
85#. module: purchase_tax_include
86#: field:purchase.order.line,price_subtotal_incl:0
87msgid "Subtotal"
88msgstr ""
89
090
=== modified file 'purchase_tax_include/purchase_tax_incl.py'
--- purchase_tax_include/purchase_tax_incl.py 2008-11-03 19:56:05 +0000
+++ purchase_tax_include/purchase_tax_incl.py 2010-07-09 15:01:37 +0000
@@ -1,99 +1,262 @@
1# -*- encoding: utf-8 -*-1# -*- encoding: utf-8 -*-
2##############################################################################2##############################################################################
3#3#
4# OpenERP, Open Source Management Solution 4# OpenERP, Open Source Management Solution
5# Copyright (C) 2004-2008 Tiny SPRL (<http://tiny.be>). All Rights Reserved5# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
6# $Id$
7#6#
8# This program is free software: you can redistribute it and/or modify7# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by8# it under the terms of the GNU Affero General Public License as
10# the Free Software Foundation, either version 3 of the License, or9# published by the Free Software Foundation, either version 3 of the
11# (at your option) any later version.10# License, or (at your option) any later version.
12#11#
13# This program is distributed in the hope that it will be useful,12# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of13# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.15# GNU Affero General Public License for more details.
17#16#
18# You should have received a copy of the GNU General Public License17# You should have received a copy of the GNU Affero General Public License
19# along with this program. If not, see <http://www.gnu.org/licenses/>.18# along with this program. If not, see <http://www.gnu.org/licenses/>.
20#19#
21##############################################################################20##############################################################################
2221
23import time22__authors__ = [
24import netsvc23 "OpenERP S.A.",
24 "Borja López Soilán (Pexego) <borjals@pexego.es>"
25]
26
25from osv import fields, osv27from osv import fields, osv
26import ir28from tools import config
2729
28class purchase_order(osv.osv):30class purchase_order(osv.osv):
31 """
32 Extends the purchase order to allow using "tax included" prices.
33 """
29 _inherit = "purchase.order"34 _inherit = "purchase.order"
30 def _amount_tax(self, cr, uid, ids, field_name, arg, context):35
36 def _amount_all(self, cr, uid, ids, field_name, arg, context):
37 """
38 Overwrites/extends the amounts calculation to allow tax included prices.
39 """
31 res = {}40 res = {}
32 cur_obj=self.pool.get('res.currency')41 cur_obj=self.pool.get('res.currency')
33 for order in self.browse(cr, uid, ids):42 for order in self.browse(cr, uid, ids):
34 val = 0.043 if order.price_type == 'tax_included':
35 cur=order.pricelist_id.currency_id44 #
36 for line in order.order_line:45 # Use the tax included calculation
37 if order.price_type=='tax_included':46 #
38 ttt = self.pool.get('account.tax').compute_inv(cr, uid, line.taxes_id, line.price_unit, line.product_qty, order.partner_address_id.id, line.product_id, order.partner_id)47 res[order.id] = {
39 else:48 'amount_untaxed': 0.0,
40 ttt = self.pool.get('account.tax').compute(cr, uid, line.taxes_id, line.price_unit, line.product_qty, order.partner_address_id.id, line.product_id, order.partner_id)49 'amount_tax': 0.0,
41 for c in ttt:50 'amount_total': 0.0,
42 val += cur_obj.round(cr, uid, cur, c['amount'])51 }
43 res[order.id]=cur_obj.round(cr, uid, cur, val)52 val = val1 = 0.0
53 cur=order.pricelist_id.currency_id
54 for line in order.order_line:
55 for c in self.pool.get('account.tax').compute_inv(cr, uid, line.taxes_id, line.price_unit, line.product_qty, order.partner_address_id.id, line.product_id, order.partner_id):
56 val+= c['amount']
57 val1 += line.price_subtotal
58 res[order.id]['amount_tax']=cur_obj.round(cr, uid, cur, val)
59 res[order.id]['amount_untaxed']=cur_obj.round(cr, uid, cur, val1)
60 res[order.id]['amount_total']=res[order.id]['amount_untaxed'] + res[order.id]['amount_tax']
61 else:
62 #
63 # Use the default calculation
64 #
65 res = super(purchase_order, self)._amount_all(cr, uid, ids, field_name, arg, context)
44 return res66 return res
67
68
69 def _get_order(self, cr, uid, ids, context={}):
70 """
71 Returns the orders that must be updated when some order lines change.
72 """
73 result = {}
74 for line in self.pool.get('purchase.order.line').browse(cr, uid, ids, context=context):
75 result[line.order_id.id] = True
76 return result.keys()
77
45 _columns = {78 _columns = {
46 'price_type': fields.selection([79 'price_type': fields.selection([
47 ('tax_included','Tax included'),80 ('tax_included','Tax included'),
48 ('tax_excluded','Tax excluded')81 ('tax_excluded','Tax excluded')
49 ], 'Price method', required=True),82 ], 'Price method', required=True),
50 'amount_tax': fields.function(_amount_tax, method=True, string='Taxes'),83 'amount_untaxed': fields.function(_amount_all, method=True, digits=(16, int(config['price_accuracy'])), string='Untaxed Amount',
84 store={
85 'purchase.order': (lambda self, cr, uid, ids, c={}: ids, ['price_type'], 20),
86 'purchase.order.line': (_get_order, None, 10),
87 }, multi="sums"),
88 'amount_tax': fields.function(_amount_all, method=True, digits=(16, int(config['price_accuracy'])), string='Taxes',
89 store={
90 'purchase.order': (lambda self, cr, uid, ids, c={}: ids, ['price_type'], 20),
91 'purchase.order.line': (_get_order, None, 10),
92 }, multi="sums"),
93 'amount_total': fields.function(_amount_all, method=True, digits=(16, int(config['price_accuracy'])), string='Total',
94 store={
95 'purchase.order': (lambda self, cr, uid, ids, c={}: ids, ['price_type'], 20),
96 'purchase.order.line': (_get_order, None, 10),
97 }, multi="sums"),
51 }98 }
99
52 _defaults = {100 _defaults = {
53 'price_type': lambda *a: 'tax_excluded',101 'price_type': lambda *a: 'tax_excluded',
54 }102 }
103
55 def _inv_get(self, cr, uid, order, context={}):104 def _inv_get(self, cr, uid, order, context={}):
105 """
106 Returns the columns as a dictionary.
107 """
56 return {108 return {
57 'price_type': order.price_type109 'price_type': order.price_type
58 }110 }
111
112
113 def action_invoice_create(self, cr, uid, ids, *args):
114 """
115 Extend the invoice creation action to set the price type if needed.
116 """
117 #
118 # Count how many orders have tax included prices.
119 #
120 tax_included_count = 0
121 orders = self.browse(cr, uid, ids)
122 for order in orders:
123 if order.price_type == 'tax_included':
124 tax_included_count += 1
125
126 if tax_included_count:
127 if len(orders) == tax_included_count:
128 #
129 # Every order has tax include prices, we must create the invoice
130 # and (afterwards) set the price type and recalculate.
131 #
132 invoice_id = super(purchase_order, self).action_invoice_create(cr, uid, ids, args)
133 self.pool.get('account.invoice').write(cr, uid, [invoice_id], { 'price_type': 'tax_included' })
134 self.pool.get('account.invoice').button_compute(cr, uid, [invoice_id], {'type': 'in_invoice'}, set_total=True)
135 else:
136 # We have no current way of creating an invoice mixing
137 # tax included and tax excluded prices, so we just fail:
138 raise osv.except_osv(_('Error!'), _("You can't mix tax included and tax excluded purchases in one invoice!"))
139 else:
140 # All the invoices are 'tax excluded', that's the default value
141 # so we just let the default method create the invoice.
142 invoice_id = super(purchase_order, self).action_invoice_create(cr, uid, ids, args)
143
144 return invoice_id
145
146
59purchase_order()147purchase_order()
60148
61class purchase_order_line(osv.osv):149class purchase_order_line(osv.osv):
150 """
151 Extends the purchase order lines to alter the calculation when
152 tax includes prices are used.
153 """
62 _inherit = 'purchase.order.line'154 _inherit = 'purchase.order.line'
155
63 def _amount_line(self, cr, uid, ids, name, arg, context):156 def _amount_line(self, cr, uid, ids, name, arg, context):
64 res = {}157 """
65 cur_obj=self.pool.get('res.currency')158 Calculate the subtotal for the line without taxes.
66 tax_obj = self.pool.get('account.tax')159 """
67 res = super(purchase_order_line, self)._amount_line(cr, uid, ids, name, arg, context)160 # Use the original method to calculate the amounts:
68 res2 = res.copy()161 res = super(purchase_order_line, self)._amount_line(cr, uid, ids, 'price_subtotal', arg, context)
69 for line in self.browse(cr, uid, ids):162 # Check if we are using 'tax_included' prices:
70 if line.order_id.price_type == 'tax_included':163 if ids and self.browse(cr, uid, ids[0]).order_id.price_type == 'tax_included':
71 if line.product_id:164 #
72 for tax in tax_obj.compute_inv(cr, uid, line.product_id.supplier_taxes_id, res[line.id]/line.product_qty, line.product_qty):165 # Tax included => Remove the taxes from the line amounts.
73 res[line.id] = res[line.id] - tax['amount']166 #
74 else:167 cur_facade=self.pool.get('res.currency')
75 for tax in tax_obj.compute_inv(cr, uid, line.taxes_id, res[line.id]/line.product_qty, line.product_qty):168 tax_facade = self.pool.get('account.tax')
76 res[line.id] = res[line.id] - tax['amount']169 for line in self.browse(cr, uid, ids):
77 if name == 'price_subtotal_incl' and line.order_id.price_type == 'tax_included':170 for tax in tax_facade.compute_inv(cr, uid, line.taxes_id, res[line.id]/line.product_qty, line.product_qty):
78 if line.product_id:171 res[line.id] = res[line.id] - tax['amount']
79 prod_taxe_ids = [ t.id for t in line.product_id.supplier_taxes_id ]172 cur = line.order_id.pricelist_id.currency_id
80 prod_taxe_ids.sort()173 res[line.id] = cur_facade.round(cr, uid, cur, res[line.id])
81 line_taxe_ids = [ t.id for t in line.taxes_id ]174 return res
82 line_taxe_ids.sort()175
83 if line.product_id and prod_taxe_ids == line_taxe_ids:176 def _amount_line_incl(self, cr, uid, ids, name, arg, context):
84 res[line.id] = res2[line.id]177 """
85 elif not line.product_id:178 Calculate the subtotal for the line with taxes.
86 res[line.id] = res2[line.id]179 """
87 else:180 # Use the original method to calculate the amounts:
88 for tax in tax_obj.compute(cr, uid, line.taxes_id, res[line.id]/line.product_qty, line.product_qty):181 res = super(purchase_order_line, self)._amount_line(cr, uid, ids, 'price_subtotal', arg, context)
89 res[line.id] = res[line.id] + tax['amount']182 # Check if we *aren't* using 'tax_included' prices on the subtotal:
90 cur = line.order_id.pricelist_id.currency_id183 if ids and self.browse(cr, uid, ids[0]).order_id.price_type != 'tax_included':
91 res[line.id] = cur_obj.round(cr, uid, cur, res[line.id])184 #
92 return res185 # Tax excluded on the subtotal => Add taxes here from the line amounts.
186 #
187 cur_facade=self.pool.get('res.currency')
188 tax_facade = self.pool.get('account.tax')
189 for line in self.browse(cr, uid, ids):
190 for tax in tax_facade.compute(cr, uid, line.taxes_id, res[line.id]/line.product_qty, line.product_qty):
191 res[line.id] = res[line.id] + tax['amount']
192 cur = line.order_id.pricelist_id.currency_id
193 res[line.id] = cur_facade.round(cr, uid, cur, res[line.id])
194 return res
195
196
93 _columns = {197 _columns = {
94 'price_subtotal': fields.function(_amount_line, method=True, string='Subtotal w/o tax'),198 'price_subtotal': fields.function(_amount_line, method=True, string='Subtotal w/o tax', digits=(16, int(config['price_accuracy']))),
95 'price_subtotal_incl': fields.function(_amount_line, method=True, string='Subtotal'),199 'price_subtotal_incl': fields.function(_amount_line_incl, method=True, string='Subtotal', digits=(16, int(config['price_accuracy']))),
96 }200 }
97purchase_order_line()201purchase_order_line()
98# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:202
203class stock_picking(osv.osv):
204 """
205 Extends the stock pickings to manage the creation of invoices with
206 tax included prices when the original order had tax included prices.
207 """
208 _inherit = 'stock.picking'
209 _description = "Picking list"
210
211 def action_invoice_create(self, cr, uid, ids, journal_id=False,
212 group=False, type='out_invoice', context=None):
213 """
214 Extend the invoice creation action to set the price type if needed.
215 """
216 #
217 # Count how many pickings have tax included prices.
218 #
219 tax_included_count = 0
220 lines_count = 0
221 pickings = self.browse(cr, uid, ids, context=context)
222 for picking in pickings:
223 #
224 # We must find the orders associated with this picking and check
225 # if they have tax included prices.
226 # As picking lines may come from different orders (even if it is
227 # not the usual), we must check it line by line.
228 #
229 for move in picking.move_lines:
230 if move.purchase_line_id and move.purchase_line_id.order_id:
231 lines_count += 1
232 if move.purchase_line_id.order_id.price_type == 'tax_included':
233 tax_included_count += 1
234
235 if tax_included_count:
236 if lines_count == tax_included_count:
237 #
238 # Every order has tax include prices, we must create the invoice
239 # and (afterwards) set the price type and recalculate.
240 #
241 invoices_map = super(stock_picking, self).action_invoice_create(cr,
242 uid, ids, journal_id=journal_id,
243 group=group, type=type,
244 context=context)
245 invoice_ids = list(set(invoices_map.values()))
246 self.pool.get('account.invoice').write(cr, uid, invoice_ids, { 'price_type': 'tax_included' })
247 self.pool.get('account.invoice').button_compute(cr, uid, invoice_ids, {'type': 'in_invoice'}, set_total=True)
248 else:
249 # We have no current way of creating an invoice mixing
250 # tax included and tax excluded prices, so we just fail:
251 raise osv.except_osv(_('Error!'), _("You can't mix tax included and tax excluded purchases in one invoice!"))
252 else:
253 # All the invoices are 'tax excluded', that's the default value
254 # so we just let the default method create the invoice.
255 invoices_map = super(stock_picking, self).action_invoice_create(cr,
256 uid, ids, journal_id=journal_id,
257 group=group, type=type,
258 context=context)
259 return invoices_map
260
261stock_picking()
99262
100263
=== modified file 'purchase_tax_include/purchase_tax_incl.xml'
--- purchase_tax_include/purchase_tax_incl.xml 2008-09-12 22:59:35 +0000
+++ purchase_tax_include/purchase_tax_incl.xml 2010-07-09 15:01:37 +0000
@@ -1,31 +1,43 @@
1<?xml version="1.0"?>1<?xml version="1.0" encoding="utf-8"?>
2<openerp>2<openerp>
3<data>3 <data>
44
5 <record model="ir.ui.view" id="account_tax_view_price">5 <record model="ir.ui.view" id="account_tax_view_price">
6 <field name="name">purchase.order.exlcuded.view.form</field>6 <field name="name">purchase.order.form.add_price_type</field>
7 <field name="type">form</field>7 <field name="type">form</field>
8 <field name="model">purchase.order</field>8 <field name="model">purchase.order</field>
9 <field name="inherit_id" ref="purchase.purchase_order_form" />9 <field name="inherit_id" ref="purchase.purchase_order_form" />
10 <field name="arch" type="xml">10 <field name="arch" type="xml">
11 <field name="origin" position="after">11 <field name="shipped" position="after">
12 <field name="price_type"/>12 <field name="price_type"/>
13 </field>13 </field>
14 </field>14 </field>
15 </record>15 </record>
1616
17 <record model="ir.ui.view" id="account_tax_view_price_subtotal_incl">17 <record model="ir.ui.view" id="account_tax_view_price_subtotal_incl">
18 <field name="name">purchase.order.line.tree</field>18 <field name="name">purchase.order.line.tree.add_price_subtotal_incl</field>
19 <field name="type">tree</field>19 <field name="type">tree</field>
20 <field name="model">purchase.order.line</field>20 <field name="model">purchase.order.line</field>
21 <field name="inherit_id" ref="purchase.purchase_order_line_tree" />21 <field name="inherit_id" ref="purchase.purchase_order_line_tree" />
22 <field name="arch" type="xml">22 <field name="arch" type="xml">
23 <field name="price_subtotal" position="after">23 <field name="price_subtotal" position="after">
24 <field name="price_subtotal_incl"/>24 <field name="price_subtotal_incl"/>
25 </field>25 </field>
26 </field>26 </field>
27 </record>27 </record>
2828
29</data>29 <record model="ir.ui.view" id="account_tax_view_price_subtotal_incl">
30 <field name="name">purchase.order.form.add_price_subtotal_incl_to_lines</field>
31 <field name="type">form</field>
32 <field name="model">purchase.order</field>
33 <field name="inherit_id" ref="purchase.purchase_order_form" />
34 <field name="arch" type="xml">
35 <xpath expr="//field[@name='order_line']/tree/field[@name='price_subtotal']" position="after">
36 <field name="price_subtotal_incl"/>
37 </xpath>
38 </field>
39 </record>
40
41 </data>
30</openerp>42</openerp>
3143