Merge lp:~openerp-community/openobject-addons/fix-account-trunk-tax-computation-method into lp:openobject-addons

Proposed by Lorenzo Battistini on 2012-05-07
Status: Needs review
Proposed branch: lp:~openerp-community/openobject-addons/fix-account-trunk-tax-computation-method
Merge into: lp:openobject-addons
Diff against target: 1101 lines (+803/-15)
14 files modified
account/__openerp__.py (+2/-0)
account/account.py (+21/-0)
account/account_invoice.py (+62/-5)
account/account_invoice_view.xml (+2/-0)
account/demo/account_tax.xml (+68/-0)
account/test/tax_computation.yml (+471/-0)
purchase/__openerp__.py (+1/-0)
purchase/purchase.py (+21/-4)
purchase/purchase_view.xml (+1/-0)
purchase/test/tax_computation.yml (+67/-0)
sale/__openerp__.py (+1/-0)
sale/sale.py (+20/-6)
sale/sale_view.xml (+1/-0)
sale/test/tax_computation.yml (+65/-0)
To merge this branch: bzr merge lp:~openerp-community/openobject-addons/fix-account-trunk-tax-computation-method
Reviewer Review Type Date Requested Status
Fabien (Open ERP) 2012-05-07 Disapprove on 2012-05-08
Olivier Dony (Odoo) 2012-05-10 Pending
Review via email: mp+104945@code.launchpad.net

Description of the change

These changes add the possibility to perform the tax computation "by column" in invoices, sale orders and purchase orders. Currently, a boolean field 'Tax Computation By Column' is added to each of these models, allowing the user to choose which computation method to use.

References:
https://bugs.launchpad.net/openobject-addons/+bug/707923
http://feedback.openerp.com/forums/77459-general-improvements/suggestions/1449257-solve-invoice-tax-rounding-issue
https://docs.google.com/document/d/1hZpHSmWyQ74Fa7jilYxaxX5QE47C6fCIk4DWBlsMYwg/edit

To post a comment you must log in.
Fabien (Open ERP) (fp-tinyerp) wrote :

This solution is too complex. I already did it months ago and I remember it's just 10 lines of code on the tax object (that should depend on a configuration on the company).

review: Disapprove
Davide Corio (enlightx) wrote :

Is this something already integrated in 6.1?
i cannot find it

btw, this cannot be a global (per company) configuration because the user must be able to select the correct vat computation method on the document.

we usually receive invoices and sale orders computed by row from USA and by column from France, for instance.

On 05/08/2012 02:44 PM, Fabien (Open ERP) wrote:
> Review: Disapprove
>
> This solution is too complex. I already did it months ago and I remember it's just 10 lines of code on the tax object (that should depend on a configuration on the company).

Hi Fabien,

if this is already fixed then that is good news. We were hit by this
issue a number of times and were pleased to see Lorenzo's effort to get
this in the core code (we used his module to the same effect until now).
Can you point to the revision or at least the lines in the code in which
you fixed this?

Cheers,
Stefan.

--
Therp - Maatwerk in open ontwikkeling

Stefan Rijnhart - Ontwerp en implementatie

mail: <email address hidden>
tel: +31 (0) 614478606
http://therp.nl
https://twitter.com/therp_stefan

Unmerged revisions

6778. By Lorenzo Battistini on 2012-05-07

[ADD] porting tax computation by column to trunk
https://code.launchpad.net/~openerp-community/openobject-addons/fix-account-6-1-tax-computation-method

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'account/__openerp__.py'
2--- account/__openerp__.py 2012-04-03 08:27:56 +0000
3+++ account/__openerp__.py 2012-05-07 17:18:21 +0000
4@@ -135,6 +135,7 @@
5 'demo/account_minimal.xml',
6 'demo/account_invoice_demo.xml',
7 # 'account_unit_test.xml',
8+ 'demo/account_tax.xml',
9 ],
10 'test': [
11 'test/account_customer_invoice.yml',
12@@ -150,6 +151,7 @@
13 'test/test_edi_invoice.yml',
14 'test/account_report.yml',
15 'test/account_fiscalyear_close_state.yml', #last test, as it will definitively close the demo fiscalyear
16+ 'test/tax_computation.yml',
17 ],
18 'installable': True,
19 'auto_install': False,
20
21=== modified file 'account/account.py'
22--- account/account.py 2012-04-03 08:29:06 +0000
23+++ account/account.py 2012-05-07 17:18:21 +0000
24@@ -3,6 +3,8 @@
25 #
26 # OpenERP, Open Source Management Solution
27 # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
28+# Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
29+# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
30 #
31 # This program is free software: you can redistribute it and/or modify
32 # it under the terms of the GNU Affero General Public License as
33@@ -1980,11 +1982,26 @@
34 'company_id': _default_company,
35 }
36 _order = 'sequence'
37+
38+ def _get_product_for_python_compute(self, cr, uid, tax, products):
39+ if ('product' in tax.python_applicable or
40+ 'product' in tax.python_compute or
41+ 'product' in tax.python_compute_inv) and len(products) > 1:
42+ raise osv.except_osv(_('Error'), _("Python computation for tax %s is configured for using 'product' variable, but the current invoice uses computation by column and the same tax covers several products") % tax.name)
43+ elif ('product' in tax.python_applicable or
44+ 'product' in tax.python_compute or
45+ 'product' in tax.python_compute_inv) and len(products) == 1:
46+ product = products[0]
47+ else:
48+ product = None
49+ return product
50
51 def _applicable(self, cr, uid, taxes, price_unit, product=None, partner=None):
52 res = []
53 for tax in taxes:
54 if tax.applicable_type=='code':
55+ if isinstance(product, list):
56+ product = self._get_product_for_python_compute(cr, uid, tax, product)
57 localdict = {'price_unit':price_unit, 'product':product, 'partner':partner}
58 exec tax.python_applicable in localdict
59 if localdict.get('result', False):
60@@ -2024,6 +2041,8 @@
61 data['tax_amount']=quantity
62 # data['amount'] = quantity
63 elif tax.type=='code':
64+ if isinstance(product, list):
65+ product = self._get_product_for_python_compute(cr, uid, tax, product)
66 localdict = {'price_unit':cur_price_unit, 'product':product, 'partner':partner}
67 exec tax.python_compute in localdict
68 amount = localdict['result']
69@@ -2146,6 +2165,8 @@
70 amount = tax.amount
71
72 elif tax.type=='code':
73+ if isinstance(product, list):
74+ product = self._get_product_for_python_compute(cr, uid, tax, product)
75 localdict = {'price_unit':cur_price_unit, 'product':product, 'partner':partner}
76 exec tax.python_compute_inv in localdict
77 amount = localdict['result']
78
79=== modified file 'account/account_invoice.py'
80--- account/account_invoice.py 2012-04-03 10:58:01 +0000
81+++ account/account_invoice.py 2012-05-07 17:18:21 +0000
82@@ -3,6 +3,8 @@
83 #
84 # OpenERP, Open Source Management Solution
85 # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
86+# Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
87+# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
88 #
89 # This program is free software: you can redistribute it and/or modify
90 # it under the terms of the GNU Affero General Public License as
91@@ -274,7 +276,8 @@
92 'payment_ids': fields.function(_compute_lines, relation='account.move.line', type="many2many", string='Payments'),
93 'move_name': fields.char('Journal Entry', size=64, readonly=True, states={'draft':[('readonly',False)]}),
94 'user_id': fields.many2one('res.users', 'Salesman', readonly=True, states={'draft':[('readonly',False)]}),
95- 'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position', readonly=True, states={'draft':[('readonly',False)]})
96+ 'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position', readonly=True, states={'draft':[('readonly',False)]}),
97+ 'vertical_comp' : fields.boolean('Tax Computation By Column'),
98 }
99 _defaults = {
100 'type': _get_type,
101@@ -1459,6 +1462,7 @@
102 continue
103 res.append(mres)
104 tax_code_found= False
105+ # computation by column needed?
106 for tax in tax_obj.compute_all(cr, uid, line.invoice_line_tax_id,
107 (line.price_unit * (1.0 - (line['discount'] or 0.0) / 100.0)),
108 line.quantity, line.product_id,
109@@ -1587,6 +1591,54 @@
110 'base_amount': 0.0,
111 'tax_amount': 0.0,
112 }
113+
114+ def build_grouped_lines(self, cr, uid, document_lines,
115+ tax_field_name='invoice_line_tax_id', price_unit_field_name='price_unit',
116+ discount_field_name='discount', quantity_field_name='quantity', product_id_field_name='product_id', account_id_field_name='account_id'):
117+ lines = []
118+ lines_grouped_by_tax = {}
119+ for line in document_lines:
120+ key = tuple(tax.id for tax in line[tax_field_name])
121+ if not lines_grouped_by_tax.get(key, False):
122+ lines_grouped_by_tax[key] = []
123+ lines_grouped_by_tax[key].append(line)
124+ for key in lines_grouped_by_tax:
125+ price_unit = 0.0
126+ products = []
127+ account_ids = []
128+ for line in lines_grouped_by_tax[key]:
129+ price_unit += (line[price_unit_field_name]* (1-(discount_field_name and line[discount_field_name] or 0.0)/100.0)) * line[quantity_field_name]
130+ if product_id_field_name and line[product_id_field_name] not in products:
131+ products.append(line.product_id)
132+ if account_id_field_name and line[account_id_field_name]['id'] not in account_ids:
133+ account_ids.append(line[account_id_field_name]['id'])
134+ lines.append({
135+ # using the first line, as being grouped by taxes, invoice_line_tax_id is always the same for every group
136+ 'taxes': lines_grouped_by_tax[key][0][tax_field_name],
137+ 'price_unit': price_unit,
138+ 'quantity': 1,
139+ 'products': products,
140+ 'account_ids': account_ids,
141+ })
142+ return lines
143+
144+ def build_invoice_line_list(self, cr, uid, invoice_id, context=None):
145+ lines = []
146+ inv = self.pool.get('account.invoice').browse(cr, uid, invoice_id, context=context)
147+ if inv.vertical_comp:
148+ lines = self.build_grouped_lines(cr, uid, inv.invoice_line)
149+ else:
150+ for line in inv.invoice_line:
151+ price_unit = (line.price_unit* (1-(line.discount or 0.0)/100.0))
152+ lines.append({
153+ 'taxes': line.invoice_line_tax_id,
154+ 'price_unit': price_unit,
155+ 'quantity': line.quantity,
156+ 'products': line.product_id,
157+ 'account_ids': [line.account_id.id],
158+ })
159+ return lines
160+
161 def compute(self, cr, uid, invoice_id, context=None):
162 tax_grouped = {}
163 tax_obj = self.pool.get('account.tax')
164@@ -1595,8 +1647,9 @@
165 cur = inv.currency_id
166 company_currency = inv.company_id.currency_id.id
167
168- for line in inv.invoice_line:
169- for tax in tax_obj.compute_all(cr, uid, line.invoice_line_tax_id, (line.price_unit* (1-(line.discount or 0.0)/100.0)), line.quantity, line.product_id, inv.partner_id)['taxes']:
170+ lines = self.build_invoice_line_list(cr, uid, invoice_id, context=None)
171+ for line in lines:
172+ for tax in tax_obj.compute_all(cr, uid, line['taxes'], line['price_unit'], line['quantity'], line['products'], inv.partner_id)['taxes']:
173 tax['price_unit'] = cur_obj.round(cr, uid, cur, tax['price_unit'])
174 val={}
175 val['invoice_id'] = inv.id
176@@ -1611,13 +1664,17 @@
177 val['tax_code_id'] = tax['tax_code_id']
178 val['base_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['base'] * tax['base_sign'], context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}, round=False)
179 val['tax_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['amount'] * tax['tax_sign'], context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}, round=False)
180- val['account_id'] = tax['account_collected_id'] or line.account_id.id
181+ if not tax['account_collected_id'] and len(line['account_ids']) > 1:
182+ raise osv.except_osv(_('Error'), _("The invoice %s is configured for using computation by column but tax %s does not have an 'account_collected_id' value and its lines cover several accounts") % (inv.name, tax['name']))
183+ val['account_id'] = tax['account_collected_id'] or line['account_ids'][0]
184 else:
185 val['base_code_id'] = tax['ref_base_code_id']
186 val['tax_code_id'] = tax['ref_tax_code_id']
187 val['base_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['base'] * tax['ref_base_sign'], context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}, round=False)
188 val['tax_amount'] = cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, val['amount'] * tax['ref_tax_sign'], context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}, round=False)
189- val['account_id'] = tax['account_paid_id'] or line.account_id.id
190+ if not tax['account_paid_id'] and len(line['account_ids']) > 1:
191+ raise osv.except_osv(_('Error'), _("The invoice %s is configured for using computation by column but tax %s does not have an 'account_paid_id' value and its lines cover several accounts") % (inv.name, tax['name']))
192+ val['account_id'] = tax['account_paid_id'] or line['account_ids'][0]
193
194 key = (val['tax_code_id'], val['base_code_id'], val['account_id'])
195 if not key in tax_grouped:
196
197=== modified file 'account/account_invoice_view.xml'
198--- account/account_invoice_view.xml 2012-04-25 13:40:18 +0000
199+++ account/account_invoice_view.xml 2012-05-07 17:18:21 +0000
200@@ -224,6 +224,7 @@
201 <field name="origin"/>
202 <field name="user_id"/>
203 <field name="move_id" groups="account.group_account_user"/>
204+ <field name="vertical_comp"/>
205 <separator colspan="4" string="Additional Information"/>
206 <field colspan="4" name="comment" nolabel="1"/>
207 </page>
208@@ -319,6 +320,7 @@
209 <field domain="[('partner_id.ref_companies', 'in', [company_id])]" name="partner_bank_id"/>
210 <field name="origin"/>
211 <field name="move_id" groups="account.group_account_user"/>
212+ <field name="vertical_comp"/>
213 <separator colspan="4" string="Additional Information"/>
214 <field colspan="4" name="comment" nolabel="1"/>
215 </page>
216
217=== added file 'account/demo/account_tax.xml'
218--- account/demo/account_tax.xml 1970-01-01 00:00:00 +0000
219+++ account/demo/account_tax.xml 2012-05-07 17:18:21 +0000
220@@ -0,0 +1,68 @@
221+<?xml version="1.0" encoding="utf-8"?>
222+<openerp>
223+ <data noupdate="1">
224+
225+ <!-- Tax codes -->
226+
227+ <record id="account_tax_code_10" model="account.tax.code">
228+ <field name="name">10 %</field>
229+ </record>
230+ <record id="account_tax_code_10_imp" model="account.tax.code">
231+ <field name="name">10 % IMP</field>
232+ </record>
233+
234+ <record id="account_tax_code_21" model="account.tax.code">
235+ <field name="name">21 %</field>
236+ </record>
237+ <record id="account_tax_code_21_imp" model="account.tax.code">
238+ <field name="name">21 % IMP</field>
239+ </record>
240+
241+ <record id="account_tax_code_21_inc" model="account.tax.code">
242+ <field name="name">21 % INC</field>
243+ </record>
244+ <record id="account_tax_code_21_inc_imp" model="account.tax.code">
245+ <field name="name">21 % INC IMP</field>
246+ </record>
247+
248+ <record id="account_tax_code_20_inc" model="account.tax.code">
249+ <field name="name">20 % INC</field>
250+ </record>
251+ <record id="account_tax_code_20_inc_imp" model="account.tax.code">
252+ <field name="name">20 % INC IMP</field>
253+ </record>
254+
255+ <!-- taxes -->
256+
257+ <record id="account_tax_10" model="account.tax">
258+ <field name="name">10 %</field>
259+ <field name="amount">0.1</field>
260+ <field name="tax_code_id" ref="account_tax_code_10"></field>
261+ <field name="base_code_id" ref="account_tax_code_10_imp"></field>
262+ </record>
263+
264+ <record id="account_tax_21" model="account.tax">
265+ <field name="name">21 %</field>
266+ <field name="amount">0.21</field>
267+ <field name="tax_code_id" ref="account_tax_code_21"></field>
268+ <field name="base_code_id" ref="account_tax_code_21_imp"></field>
269+ </record>
270+
271+ <record id="account_tax_21_inc" model="account.tax">
272+ <field name="name">21 % INC</field>
273+ <field name="amount">0.21</field>
274+ <field name="price_include">1</field>
275+ <field name="tax_code_id" ref="account_tax_code_21_inc"></field>
276+ <field name="base_code_id" ref="account_tax_code_21_inc_imp"></field>
277+ </record>
278+
279+ <record id="account_tax_20_inc" model="account.tax">
280+ <field name="name">20 % INC</field>
281+ <field name="amount">0.2</field>
282+ <field name="price_include">1</field>
283+ <field name="tax_code_id" ref="account_tax_code_20_inc"></field>
284+ <field name="base_code_id" ref="account_tax_code_20_inc_imp"></field>
285+ </record>
286+
287+ </data>
288+</openerp>
289
290=== added file 'account/test/tax_computation.yml'
291--- account/test/tax_computation.yml 1970-01-01 00:00:00 +0000
292+++ account/test/tax_computation.yml 2012-05-07 17:18:21 +0000
293@@ -0,0 +1,471 @@
294+#-
295+ #First invoice. 2 lines
296+ #price_unit = 23.83, tax = 0.21
297+ #price_unit = 7.44, tax = 0.21
298+#-
299+-
300+ Computation by line
301+-
302+
303+ !record {model: account.invoice, id: invoice_1_computation_by_line}:
304+ account_id: a_recv
305+ company_id: base.main_company
306+ currency_id: base.EUR
307+ date_invoice: !eval time.strftime('%Y-%m-%d')
308+ vertical_comp: 0
309+ invoice_line:
310+ - account_id: a_sale
311+ name: '23.83'
312+ price_unit: 23.83
313+ quantity: 1.0
314+ invoice_line_tax_id:
315+ - account_tax_21
316+ - account_id: a_sale
317+ name: '7.44'
318+ price_unit: 7.44
319+ quantity: 1.0
320+ invoice_line_tax_id:
321+ - account_tax_21
322+ journal_id: sales_journal
323+ partner_id: base.res_partner_3
324+
325+-
326+ Compute the total tax.
327+-
328+ !python {model: account.invoice}: |
329+ self.button_compute(cr, uid, [ref("invoice_1_computation_by_line")])
330+-
331+ Then I verify the amount (computation by line).
332+ 23.83 × 0.21 = 5.0043 = 5
333+ 7.44 × 0.21 = 1.5624 = 1.56
334+ 5 + 1.56 = 6.56
335+-
336+ !assert {model: account.invoice, id: invoice_1_computation_by_line}:
337+ - amount_tax == 6.56
338+
339+-
340+ Computation by column
341+-
342+ !record {model: account.invoice, id: invoice_1_computation_by_column}:
343+ account_id: a_recv
344+ company_id: base.main_company
345+ currency_id: base.EUR
346+ date_invoice: !eval time.strftime('%Y-%m-%d')
347+ vertical_comp: 1
348+ invoice_line:
349+ - account_id: a_sale
350+ name: '23.83'
351+ price_unit: 23.83
352+ quantity: 1.0
353+ invoice_line_tax_id:
354+ - account_tax_21
355+ - account_id: a_sale
356+ name: '7.44'
357+ price_unit: 7.44
358+ quantity: 1.0
359+ invoice_line_tax_id:
360+ - account_tax_21
361+ journal_id: sales_journal
362+ partner_id: base.res_partner_3
363+
364+-
365+ Compute the total tax.
366+-
367+ !python {model: account.invoice}: |
368+ self.button_compute(cr, uid, [ref("invoice_1_computation_by_column")])
369+-
370+ Then I verify the amount (computation by column).
371+ 23.83 + 7.44 = 31.27
372+ 31.27 × 0.21 = 6.5667 = 6.57
373+-
374+ !assert {model: account.invoice, id: invoice_1_computation_by_column}:
375+ - amount_tax == 6.57
376+
377+
378+#-
379+ #Second invoice. 2 lines
380+ #price_unit = 24.92, tax = 0.21
381+ #price_unit = 7.44, tax = 0.21
382+#-
383+-
384+ Computation by line
385+-
386+ !record {model: account.invoice, id: invoice_2_computation_by_line}:
387+ account_id: a_recv
388+ company_id: base.main_company
389+ currency_id: base.EUR
390+ date_invoice: !eval time.strftime('%Y-%m-%d')
391+ vertical_comp: 0
392+ invoice_line:
393+ - account_id: a_sale
394+ name: '24.92'
395+ price_unit: 24.92
396+ quantity: 1.0
397+ invoice_line_tax_id:
398+ - account_tax_21
399+ - account_id: a_sale
400+ name: '7.44'
401+ price_unit: 7.44
402+ quantity: 1.0
403+ invoice_line_tax_id:
404+ - account_tax_21
405+ journal_id: sales_journal
406+ partner_id: base.res_partner_3
407+
408+-
409+ Compute the total tax.
410+-
411+ !python {model: account.invoice}: |
412+ self.button_compute(cr, uid, [ref("invoice_2_computation_by_line")])
413+-
414+ Then I verify the amount (computation by line).
415+ 24.92 × 0.21 = 5.2332 = 5.23
416+ 7.44 × 0.21 = 1.5624 = 1.56
417+ 5.23 + 1.56 = 6.79
418+-
419+ !assert {model: account.invoice, id: invoice_2_computation_by_line}:
420+ - amount_tax == 6.79
421+-
422+ Computation by column
423+-
424+ !record {model: account.invoice, id: invoice_2_computation_by_column}:
425+ account_id: a_recv
426+ company_id: base.main_company
427+ currency_id: base.EUR
428+ date_invoice: !eval time.strftime('%Y-%m-%d')
429+ vertical_comp: 1
430+ invoice_line:
431+ - account_id: a_sale
432+ name: '24.92'
433+ price_unit: 24.92
434+ quantity: 1.0
435+ invoice_line_tax_id:
436+ - account_tax_21
437+ - account_id: a_sale
438+ name: '7.44'
439+ price_unit: 7.44
440+ quantity: 1.0
441+ invoice_line_tax_id:
442+ - account_tax_21
443+ journal_id: sales_journal
444+ partner_id: base.res_partner_3
445+
446+-
447+ Compute the total tax.
448+-
449+ !python {model: account.invoice}: |
450+ self.button_compute(cr, uid, [ref("invoice_2_computation_by_column")])
451+-
452+ Then I verify the amount (computation by column).
453+ 24.92 + 7.44 = 32.36
454+ 32.36 × 0.21 = 6.7956 = 6.8
455+-
456+ !assert {model: account.invoice, id: invoice_2_computation_by_column}:
457+ - amount_tax == 6.8
458+
459+
460+#-
461+ #Third invoice. 6 lines
462+ #price_unit = 1.99, tax = 0.1
463+ #price_unit = 0.38, tax = 0.1
464+ #price_unit = 5.68, tax = 0.1
465+ #price_unit = 0.45, tax = 0.1
466+ #price_unit = 1.05, tax = 0.1
467+ #price_unit = 2.87, tax = 0.1
468+#-
469+-
470+ Computation by line
471+-
472+ !record {model: account.invoice, id: invoice_3_computation_by_line}:
473+ account_id: a_recv
474+ company_id: base.main_company
475+ currency_id: base.EUR
476+ date_invoice: !eval time.strftime('%Y-%m-%d')
477+ vertical_comp: 0
478+ invoice_line:
479+ - account_id: a_sale
480+ name: '1.99'
481+ price_unit: 1.99
482+ quantity: 1.0
483+ invoice_line_tax_id:
484+ - account_tax_10
485+ - account_id: a_sale
486+ name: '0.38'
487+ price_unit: 0.38
488+ quantity: 1.0
489+ invoice_line_tax_id:
490+ - account_tax_10
491+ - account_id: a_sale
492+ name: '5.68'
493+ price_unit: 5.68
494+ quantity: 1.0
495+ invoice_line_tax_id:
496+ - account_tax_10
497+ - account_id: a_sale
498+ name: '0.45'
499+ price_unit: 0.45
500+ quantity: 1.0
501+ invoice_line_tax_id:
502+ - account_tax_10
503+ - account_id: a_sale
504+ name: '1.05'
505+ price_unit: 1.05
506+ quantity: 1.0
507+ invoice_line_tax_id:
508+ - account_tax_10
509+ - account_id: a_sale
510+ name: '2.87'
511+ price_unit: 2.87
512+ quantity: 1.0
513+ invoice_line_tax_id:
514+ - account_tax_10
515+ journal_id: sales_journal
516+ partner_id: base.res_partner_3
517+
518+-
519+ Compute the total tax.
520+-
521+ !python {model: account.invoice}: |
522+ self.button_compute(cr, uid, [ref("invoice_3_computation_by_line")])
523+-
524+ Then I verify the amount (computation by line).
525+ 1.99 × 0.1 = 0.199 = 0.2
526+ 0.38 × 0.1 = 0.038 = 0.04
527+ 5.68 × 0.1 = 0.568 = 0.57
528+ 0.45 × 0.1 = 0.045 = 0.05
529+ 1.05 × 0.1 = 0.105 = 0.11
530+ 2.87 × 0.1 = 0.287 = 0.29
531+ 0.2 + 0.04 + 0.57 + 0.05 + 0.11 + 0.29 = 1.26
532+-
533+ !assert {model: account.invoice, id: invoice_3_computation_by_line}:
534+ - amount_tax == 1.26
535+-
536+ Computation by column
537+-
538+ !record {model: account.invoice, id: invoice_3_computation_by_column}:
539+ account_id: a_recv
540+ company_id: base.main_company
541+ currency_id: base.EUR
542+ date_invoice: !eval time.strftime('%Y-%m-%d')
543+ vertical_comp: 1
544+ invoice_line:
545+ - account_id: a_sale
546+ name: '1.99'
547+ price_unit: 1.99
548+ quantity: 1.0
549+ invoice_line_tax_id:
550+ - account_tax_10
551+ - account_id: a_sale
552+ name: '0.38'
553+ price_unit: 0.38
554+ quantity: 1.0
555+ invoice_line_tax_id:
556+ - account_tax_10
557+ - account_id: a_sale
558+ name: '5.68'
559+ price_unit: 5.68
560+ quantity: 1.0
561+ invoice_line_tax_id:
562+ - account_tax_10
563+ - account_id: a_sale
564+ name: '0.45'
565+ price_unit: 0.45
566+ quantity: 1.0
567+ invoice_line_tax_id:
568+ - account_tax_10
569+ - account_id: a_sale
570+ name: '1.05'
571+ price_unit: 1.05
572+ quantity: 1.0
573+ invoice_line_tax_id:
574+ - account_tax_10
575+ - account_id: a_sale
576+ name: '2.87'
577+ price_unit: 2.87
578+ quantity: 1.0
579+ invoice_line_tax_id:
580+ - account_tax_10
581+ journal_id: sales_journal
582+ partner_id: base.res_partner_3
583+
584+-
585+ Compute the total tax.
586+-
587+ !python {model: account.invoice}: |
588+ self.button_compute(cr, uid, [ref("invoice_3_computation_by_column")])
589+-
590+ Then I verify the amount (computation by column).
591+ 1.99 + 0.38 + 5.68 + 0.45 + 1.05 + 2.87 = 12.42
592+ 12.42 * 0.1 = 1.242 = 1.24
593+-
594+ !assert {model: account.invoice, id: invoice_3_computation_by_column}:
595+ - amount_tax == 1.24
596+
597+
598+#-
599+ #Fourth invoice. 2 lines
600+ #price_unit = 465, tax = 0.21 included in price
601+ #price_unit = 9, tax = 0.21 included in price
602+#-
603+-
604+ Computation by line
605+-
606+ !record {model: account.invoice, id: invoice_4_computation_by_line}:
607+ account_id: a_recv
608+ company_id: base.main_company
609+ currency_id: base.EUR
610+ date_invoice: !eval time.strftime('%Y-%m-%d')
611+ vertical_comp: 0
612+ invoice_line:
613+ - account_id: a_sale
614+ name: '465'
615+ price_unit: 465
616+ quantity: 1.0
617+ invoice_line_tax_id:
618+ - account_tax_21_inc
619+ - account_id: a_sale
620+ name: '9'
621+ price_unit: 9
622+ quantity: 1.0
623+ invoice_line_tax_id:
624+ - account_tax_21_inc
625+ journal_id: sales_journal
626+ partner_id: base.res_partner_3
627+
628+-
629+ Compute the total tax.
630+-
631+ !python {model: account.invoice}: |
632+ self.button_compute(cr, uid, [ref("invoice_4_computation_by_line")])
633+-
634+ Then I verify the amount (computation by line).
635+ 465 ÷ 1.21 = 384.297520661 = 384.3
636+ 9 ÷ 1.21 = 7.438016529 = 7.44
637+ 465 + 9 = 474
638+ 384.3 + 7.44 = 391.74
639+ 474 − 391.74 = 82.26
640+-
641+ !assert {model: account.invoice, id: invoice_4_computation_by_line}:
642+ - amount_tax == 82.26
643+-
644+ Computation by column
645+-
646+ !record {model: account.invoice, id: invoice_4_computation_by_column}:
647+ account_id: a_recv
648+ company_id: base.main_company
649+ currency_id: base.EUR
650+ date_invoice: !eval time.strftime('%Y-%m-%d')
651+ vertical_comp: 1
652+ invoice_line:
653+ - account_id: a_sale
654+ name: '465'
655+ price_unit: 465
656+ quantity: 1.0
657+ invoice_line_tax_id:
658+ - account_tax_21_inc
659+ - account_id: a_sale
660+ name: '9'
661+ price_unit: 9
662+ quantity: 1.0
663+ invoice_line_tax_id:
664+ - account_tax_21_inc
665+ journal_id: sales_journal
666+ partner_id: base.res_partner_3
667+
668+-
669+ Compute the total tax.
670+-
671+ !python {model: account.invoice}: |
672+ self.button_compute(cr, uid, [ref("invoice_4_computation_by_column")])
673+-
674+ Then I verify the amount (computation by column).
675+ 465 + 9 = 474
676+ 474 ÷ 1.21 = 391.73553719 = 391.74
677+ 474 − 391.74 = 82.26
678+-
679+ !assert {model: account.invoice, id: invoice_4_computation_by_column}:
680+ - amount_tax == 82.26
681+
682+
683+#-
684+ #Fifth invoice. 2 lines
685+ #price_unit = 148.28, tax = 0.2 included in price
686+ #price_unit = 148.28, tax = 0.2 included in price
687+#-
688+-
689+ Computation by line
690+-
691+ !record {model: account.invoice, id: invoice_5_computation_by_line}:
692+ account_id: a_recv
693+ company_id: base.main_company
694+ currency_id: base.EUR
695+ date_invoice: !eval time.strftime('%Y-%m-%d')
696+ vertical_comp: 0
697+ invoice_line:
698+ - account_id: a_sale
699+ name: '148.28'
700+ price_unit: 148.28
701+ quantity: 1.0
702+ invoice_line_tax_id:
703+ - account_tax_20_inc
704+ - account_id: a_sale
705+ name: '148.28'
706+ price_unit: 148.28
707+ quantity: 1.0
708+ invoice_line_tax_id:
709+ - account_tax_20_inc
710+ journal_id: sales_journal
711+ partner_id: base.res_partner_3
712+
713+-
714+ Compute the total tax.
715+-
716+ !python {model: account.invoice}: |
717+ self.button_compute(cr, uid, [ref("invoice_5_computation_by_line")])
718+-
719+ Then I verify the amount (computation by line).
720+ 148.28 + 148.28 = 296.56
721+ 148.28 ÷ 1.2 = 123.566666667 = 123.57
722+ 123.57 × 2 = 247.14
723+ 296.56 - 247.14 = 49.42
724+-
725+ !assert {model: account.invoice, id: invoice_5_computation_by_line}:
726+ - amount_tax == 49.42
727+-
728+ Computation by column
729+-
730+ !record {model: account.invoice, id: invoice_5_computation_by_column}:
731+ account_id: a_recv
732+ company_id: base.main_company
733+ currency_id: base.EUR
734+ date_invoice: !eval time.strftime('%Y-%m-%d')
735+ vertical_comp: 1
736+ invoice_line:
737+ - account_id: a_sale
738+ name: '148.28'
739+ price_unit: 148.28
740+ quantity: 1.0
741+ invoice_line_tax_id:
742+ - account_tax_20_inc
743+ - account_id: a_sale
744+ name: '148.28'
745+ price_unit: 148.28
746+ quantity: 1.0
747+ invoice_line_tax_id:
748+ - account_tax_20_inc
749+ journal_id: sales_journal
750+ partner_id: base.res_partner_3
751+
752+-
753+ Compute the total tax.
754+-
755+ !python {model: account.invoice}: |
756+ self.button_compute(cr, uid, [ref("invoice_5_computation_by_column")])
757+-
758+ Then I verify the amount (computation by column).
759+ 148.28 + 148.28 = 296.56
760+ 296.56 ÷ 1.2 = 247.133333333 = 247.13
761+ 296.56 - 247.13 = 49.43
762+-
763+ !assert {model: account.invoice, id: invoice_5_computation_by_column}:
764+ - amount_tax == 49.43
765
766=== modified file 'purchase/__openerp__.py'
767--- purchase/__openerp__.py 2012-04-03 13:26:18 +0000
768+++ purchase/__openerp__.py 2012-05-07 17:18:21 +0000
769@@ -72,6 +72,7 @@
770 'test/ui/print_report.yml',
771 'test/ui/duplicate_order.yml',
772 'test/ui/delete_order.yml',
773+ 'test/tax_computation.yml',
774 ],
775 'demo': [
776 'purchase_order_demo.yml',
777
778=== modified file 'purchase/purchase.py'
779--- purchase/purchase.py 2012-05-03 10:29:10 +0000
780+++ purchase/purchase.py 2012-05-07 17:18:21 +0000
781@@ -3,6 +3,8 @@
782 #
783 # OpenERP, Open Source Management Solution
784 # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
785+# Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
786+# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
787 #
788 # This program is free software: you can redistribute it and/or modify
789 # it under the terms of the GNU Affero General Public License as
790@@ -39,6 +41,8 @@
791 def _amount_all(self, cr, uid, ids, field_name, arg, context=None):
792 res = {}
793 cur_obj=self.pool.get('res.currency')
794+ ait_pool = self.pool.get('account.invoice.tax')
795+ tax_pool = self.pool.get('account.tax')
796 for order in self.browse(cr, uid, ids, context=context):
797 res[order.id] = {
798 'amount_untaxed': 0.0,
799@@ -48,11 +52,20 @@
800 val = val1 = 0.0
801 cur = order.pricelist_id.currency_id
802 for line in order.order_line:
803- val1 += line.price_subtotal
804- for c in self.pool.get('account.tax').compute_all(cr, uid, line.taxes_id, line.price_unit, line.product_qty, line.product_id.id, order.partner_id)['taxes']:
805- val += c.get('amount', 0.0)
806+ val1 += line.price_subtotal
807+ res[order.id]['amount_untaxed'] = cur_obj.round(cr, uid, cur, val1)
808+ if order.vertical_comp:
809+ lines = ait_pool.build_grouped_lines(cr, uid, order.order_line,
810+ tax_field_name='taxes_id', quantity_field_name='product_qty', account_id_field_name=None, discount_field_name=None)
811+ for line in lines:
812+ for c in tax_pool.compute_all(cr, uid, line['taxes'], line['price_unit'], line['quantity'], line['products'], order.partner_id)['taxes']:
813+ val += c.get('amount', 0.0)
814+ res[order.id]['amount_tax'] = cur_obj.round(cr, uid, cur, val)
815+ else:
816+ for line in order.order_line:
817+ for c in self.pool.get('account.tax').compute_all(cr, uid, line.taxes_id, line.price_unit, line.product_qty, line.product_id.id, order.partner_id)['taxes']:
818+ val += c.get('amount', 0.0)
819 res[order.id]['amount_tax']=cur_obj.round(cr, uid, cur, val)
820- res[order.id]['amount_untaxed']=cur_obj.round(cr, uid, cur, val1)
821 res[order.id]['amount_total']=res[order.id]['amount_untaxed'] + res[order.id]['amount_tax']
822 return res
823
824@@ -191,20 +204,24 @@
825 ),
826 'amount_untaxed': fields.function(_amount_all, digits_compute= dp.get_precision('Purchase Price'), string='Untaxed Amount',
827 store={
828+ 'purchase.order': (lambda self, cr, uid, ids, c={}: ids, ['vertical_comp'], 10),
829 'purchase.order.line': (_get_order, None, 10),
830 }, multi="sums", help="The amount without tax"),
831 'amount_tax': fields.function(_amount_all, digits_compute= dp.get_precision('Purchase Price'), string='Taxes',
832 store={
833+ 'purchase.order': (lambda self, cr, uid, ids, c={}: ids, ['vertical_comp'], 10),
834 'purchase.order.line': (_get_order, None, 10),
835 }, multi="sums", help="The tax amount"),
836 'amount_total': fields.function(_amount_all, digits_compute= dp.get_precision('Purchase Price'), string='Total',
837 store={
838+ 'purchase.order': (lambda self, cr, uid, ids, c={}: ids, ['vertical_comp'], 10),
839 'purchase.order.line': (_get_order, None, 10),
840 }, multi="sums",help="The total amount"),
841 'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position'),
842 'product_id': fields.related('order_line','product_id', type='many2one', relation='product.product', string='Product'),
843 'create_uid': fields.many2one('res.users', 'Responsible'),
844 'company_id': fields.many2one('res.company','Company',required=True,select=1),
845+ 'vertical_comp' : fields.boolean('Tax Computation By Column'),
846 }
847 _defaults = {
848 'date_order': fields.date.context_today,
849
850=== modified file 'purchase/purchase_view.xml'
851--- purchase/purchase_view.xml 2012-04-25 13:22:02 +0000
852+++ purchase/purchase_view.xml 2012-05-07 17:18:21 +0000
853@@ -140,6 +140,7 @@
854 <field name="partner_ref"/>
855 <field name="shipped"/>
856 <field name="company_id" groups="base.group_multi_company" widget="selection"/>
857+ <field name="vertical_comp"/>
858 </group>
859 <notebook colspan="4">
860 <page string="Purchase Order">
861
862=== added file 'purchase/test/tax_computation.yml'
863--- purchase/test/tax_computation.yml 1970-01-01 00:00:00 +0000
864+++ purchase/test/tax_computation.yml 2012-05-07 17:18:21 +0000
865@@ -0,0 +1,67 @@
866+#-
867+ #First order. 2 lines
868+ #price_unit = 23.83, tax = 0.21
869+ #price_unit = 7.44, tax = 0.21
870+#-
871+-
872+ Computation by line
873+-
874+ !record {model: purchase.order, id: order_1_computation_by_line}:
875+ partner_id: base.res_partner_agrolait
876+ location_id: stock.stock_location_3
877+ pricelist_id: 1
878+ vertical_comp: 0
879+ order_line:
880+ - product_qty: 1.0
881+ product_uom: 1
882+ price_unit: 23.83
883+ name: '23.83'
884+ taxes_id:
885+ - account.account_tax_21
886+ date_planned: '2012-05-06'
887+ - product_qty: 1.0
888+ product_uom: 1
889+ price_unit: 7.44
890+ name: '7.44'
891+ taxes_id:
892+ - account.account_tax_21
893+ date_planned: '2012-05-06'
894+-
895+ Then I verify the amount (computation by line).
896+ 23.83 × 0.21 = 5.0043 = 5
897+ 7.44 × 0.21 = 1.5624 = 1.56
898+ 5 + 1.56 = 6.56
899+-
900+ !assert {model: purchase.order, id: order_1_computation_by_line}:
901+ - amount_tax == 6.56
902+
903+-
904+ Computation by column
905+-
906+ !record {model: purchase.order, id: order_1_computation_by_column}:
907+ partner_id: base.res_partner_agrolait
908+ location_id: stock.stock_location_3
909+ pricelist_id: 1
910+ vertical_comp: 1
911+ order_line:
912+ - product_qty: 1.0
913+ product_uom: 1
914+ price_unit: 23.83
915+ name: '23.83'
916+ taxes_id:
917+ - account.account_tax_21
918+ date_planned: '2012-05-06'
919+ - product_qty: 1.0
920+ product_uom: 1
921+ price_unit: 7.44
922+ name: '7.44'
923+ taxes_id:
924+ - account.account_tax_21
925+ date_planned: '2012-05-06'
926+-
927+ Then I verify the amount (computation by column).
928+ 23.83 + 7.44 = 31.27
929+ 31.27 × 0.21 = 6.5667 = 6.57
930+-
931+ !assert {model: purchase.order, id: order_1_computation_by_column}:
932+ - amount_tax == 6.57
933
934=== modified file 'sale/__openerp__.py'
935--- sale/__openerp__.py 2012-04-27 13:12:41 +0000
936+++ sale/__openerp__.py 2012-05-07 17:18:21 +0000
937@@ -96,6 +96,7 @@
938 'test/cancel_order.yml',
939 'test/delete_order.yml',
940 'test/edi_sale_order.yml',
941+ 'test/tax_computation.yml',
942 ],
943 'installable': True,
944 'auto_install': False,
945
946=== modified file 'sale/sale.py'
947--- sale/sale.py 2012-04-27 13:33:26 +0000
948+++ sale/sale.py 2012-05-07 17:18:21 +0000
949@@ -3,6 +3,8 @@
950 #
951 # OpenERP, Open Source Management Solution
952 # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
953+# Copyright (C) 2012 Agile Business Group sagl (<http://www.agilebg.com>)
954+# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
955 #
956 # This program is free software: you can redistribute it and/or modify
957 # it under the terms of the GNU Affero General Public License as
958@@ -73,6 +75,8 @@
959
960 def _amount_all(self, cr, uid, ids, field_name, arg, context=None):
961 cur_obj = self.pool.get('res.currency')
962+ ait_pool = self.pool.get('account.invoice.tax')
963+ tax_pool = self.pool.get('account.tax')
964 res = {}
965 for order in self.browse(cr, uid, ids, context=context):
966 res[order.id] = {
967@@ -84,8 +88,17 @@
968 cur = order.pricelist_id.currency_id
969 for line in order.order_line:
970 val1 += line.price_subtotal
971- val += self._amount_line_tax(cr, uid, line, context=context)
972- res[order.id]['amount_tax'] = cur_obj.round(cr, uid, cur, val)
973+ if order.vertical_comp:
974+ lines = ait_pool.build_grouped_lines(cr, uid, order.order_line,
975+ tax_field_name='tax_id', quantity_field_name='product_uom_qty', account_id_field_name=None)
976+ for line in lines:
977+ for c in tax_pool.compute_all(cr, uid, line['taxes'], line['price_unit'], line['quantity'], line['products'], order.partner_id)['taxes']:
978+ val += c.get('amount', 0.0)
979+ res[order.id]['amount_tax'] = cur_obj.round(cr, uid, cur, val)
980+ else:
981+ for line in order.order_line:
982+ val += self._amount_line_tax(cr, uid, line, context=context)
983+ res[order.id]['amount_tax'] = cur_obj.round(cr, uid, cur, val)
984 res[order.id]['amount_untaxed'] = cur_obj.round(cr, uid, cur, val1)
985 res[order.id]['amount_total'] = res[order.id]['amount_untaxed'] + res[order.id]['amount_tax']
986 return res
987@@ -248,19 +261,19 @@
988
989 'amount_untaxed': fields.function(_amount_all, digits_compute= dp.get_precision('Sale Price'), string='Untaxed Amount',
990 store = {
991- 'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line'], 10),
992+ 'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line', 'vertical_comp'], 10),
993 'sale.order.line': (_get_order, ['price_unit', 'tax_id', 'discount', 'product_uom_qty'], 10),
994 },
995 multi='sums', help="The amount without tax."),
996 'amount_tax': fields.function(_amount_all, digits_compute= dp.get_precision('Sale Price'), string='Taxes',
997 store = {
998- 'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line'], 10),
999+ 'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line', 'vertical_comp'], 10),
1000 'sale.order.line': (_get_order, ['price_unit', 'tax_id', 'discount', 'product_uom_qty'], 10),
1001 },
1002 multi='sums', help="The tax amount."),
1003 'amount_total': fields.function(_amount_all, digits_compute= dp.get_precision('Sale Price'), string='Total',
1004 store = {
1005- 'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line'], 10),
1006+ 'sale.order': (lambda self, cr, uid, ids, c={}: ids, ['order_line', 'vertical_comp'], 10),
1007 'sale.order.line': (_get_order, ['price_unit', 'tax_id', 'discount', 'product_uom_qty'], 10),
1008 },
1009 multi='sums', help="The total amount."),
1010@@ -268,7 +281,8 @@
1011 'invoice_quantity': fields.selection([('order', 'Ordered Quantities'), ('procurement', 'Shipped Quantities')], 'Invoice on', help="The sale order will automatically create the invoice proposition (draft invoice). Ordered and delivered quantities may not be the same. You have to choose if you want your invoice based on ordered or shipped quantities. If the product is a service, shipped quantities means hours spent on the associated tasks.", required=True, readonly=True, states={'draft': [('readonly', False)]}),
1012 'payment_term': fields.many2one('account.payment.term', 'Payment Term'),
1013 'fiscal_position': fields.many2one('account.fiscal.position', 'Fiscal Position'),
1014- 'company_id': fields.related('shop_id','company_id',type='many2one',relation='res.company',string='Company',store=True,readonly=True)
1015+ 'company_id': fields.related('shop_id','company_id',type='many2one',relation='res.company',string='Company',store=True,readonly=True),
1016+ 'vertical_comp' : fields.boolean('Tax Computation By Column'),
1017 }
1018 _defaults = {
1019 'picking_policy': 'direct',
1020
1021=== modified file 'sale/sale_view.xml'
1022--- sale/sale_view.xml 2012-05-03 10:29:10 +0000
1023+++ sale/sale_view.xml 2012-05-07 17:18:21 +0000
1024@@ -239,6 +239,7 @@
1025 <field name="payment_term" widget="selection"/>
1026 <field name="fiscal_position" widget="selection"/>
1027 <field name="company_id" widget="selection" groups="base.group_multi_company"/>
1028+ <field name="vertical_comp"/>
1029 </group>
1030 <separator colspan="4" string="Notes" groups="base.group_sale_notes_subtotal"/>
1031 <field colspan="4" name="note" nolabel="1" groups="base.group_sale_notes_subtotal"/>
1032
1033=== added file 'sale/test/tax_computation.yml'
1034--- sale/test/tax_computation.yml 1970-01-01 00:00:00 +0000
1035+++ sale/test/tax_computation.yml 2012-05-07 17:18:21 +0000
1036@@ -0,0 +1,65 @@
1037+#-
1038+ #First order. 2 lines
1039+ #price_unit = 23.83, tax = 0.21
1040+ #price_unit = 7.44, tax = 0.21
1041+#-
1042+-
1043+ Computation by line
1044+-
1045+ !record {model: sale.order, id: order_1_computation_by_line}:
1046+ partner_id: base.res_partner_agrolait
1047+ partner_invoice_id: base.res_partner_address_8invoice
1048+ partner_shipping_id: base.res_partner_address_8invoice
1049+ pricelist_id: 1
1050+ vertical_comp: 0
1051+ order_line:
1052+ - product_uom_qty: 1.0
1053+ product_uom: 1
1054+ price_unit: 23.83
1055+ name: '23.83'
1056+ tax_id:
1057+ - account.account_tax_21
1058+ - product_uom_qty: 1.0
1059+ product_uom: 1
1060+ price_unit: 7.44
1061+ name: '7.44'
1062+ tax_id:
1063+ - account.account_tax_21
1064+-
1065+ Then I verify the amount (computation by line).
1066+ 23.83 × 0.21 = 5.0043 = 5
1067+ 7.44 × 0.21 = 1.5624 = 1.56
1068+ 5 + 1.56 = 6.56
1069+-
1070+ !assert {model: sale.order, id: order_1_computation_by_line}:
1071+ - amount_tax == 6.56
1072+
1073+-
1074+ Computation by column
1075+-
1076+ !record {model: sale.order, id: order_1_computation_by_column}:
1077+ partner_id: base.res_partner_agrolait
1078+ partner_invoice_id: base.res_partner_address_8invoice
1079+ partner_shipping_id: base.res_partner_address_8invoice
1080+ pricelist_id: 1
1081+ vertical_comp: 1
1082+ order_line:
1083+ - product_uom_qty: 1.0
1084+ product_uom: 1
1085+ price_unit: 23.83
1086+ name: '23.83'
1087+ tax_id:
1088+ - account.account_tax_21
1089+ - product_uom_qty: 1.0
1090+ product_uom: 1
1091+ price_unit: 7.44
1092+ name: '7.44'
1093+ tax_id:
1094+ - account.account_tax_21
1095+-
1096+ Then I verify the amount (computation by column).
1097+ 23.83 + 7.44 = 31.27
1098+ 31.27 × 0.21 = 6.5667 = 6.57
1099+-
1100+ !assert {model: sale.order, id: order_1_computation_by_column}:
1101+ - amount_tax == 6.57

Subscribers

People subscribed via source and target branches

to all changes: