Merge lp:~openerp-community/openobject-addons/fix-account-trunk-tax-computation-method into lp:openobject-addons
- fix-account-trunk-tax-computation-method
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Fabien (Open ERP) | Disapprove | ||
Olivier Dony (Odoo) | Pending | ||
Review via email: mp+104945@code.launchpad.net |
Commit message
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:/
http://
https:/
Davide Corio (enlightx-deactivatedaccount) 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.
Stefan Rijnhart (Opener) (stefan-opener) wrote : | # |
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://
https:/
Unmerged revisions
- 6778. By Lorenzo Battistini
-
[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
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 |
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).