Merge lp:~akretion-team/openobject-addons/trunk-addons-analytic-on-tax into lp:openobject-addons

Proposed by Alexis de Lattre
Status: Superseded
Proposed branch: lp:~akretion-team/openobject-addons/trunk-addons-analytic-on-tax
Merge into: lp:openobject-addons
Diff against target: 173 lines (+58/-8)
4 files modified
account/account.py (+8/-2)
account/account_invoice.py (+46/-4)
account/account_invoice_view.xml (+2/-0)
account/account_view.xml (+2/-2)
To merge this branch: bzr merge lp:~akretion-team/openobject-addons/trunk-addons-analytic-on-tax
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+114182@code.launchpad.net

This proposal supersedes a proposal from 2011-12-11.

This proposal has been superseded by a proposal from 2012-07-10.

Description of the change

Here is the real-life scenario which motivate this merge proposal :
In some companies, all expenses must have an analytic account.
When you purchase some equipments, you sometimes have to pay an eco-tax. For the company who is the end-used of the equipment, this eco-tax is considered as an expense. So we need to be able to define an analytic account on invoice tax lines.

More info about the history of this topic : https://lists.launchpad.net/openerp-expert-accounting/msg01257.html

This merge proposal :
- adds a field 'account_analytic_id' on the object account_invoice_tax.
- adds 2 fields 'account_analytic_collected_id' and 'account_analytic_paid_id' on the object account_tax so as to be able to define default analytic accounts for invoices and refunds (similar behavior as for general accounts on taxes).
- adds these 3 fields in the appropriate views
- adds the necessary code in account.py and account_invoice.py
- moves the help message "Keep empty to use the income account" from a label on the form view of account_tax to the help pop-up of the corresponding field (I made this change in order to get some room for the fields 'account_analytic_collected_id' and 'account_analytic_paid_id' next to their general accounting conterparts on the form view).

To post a comment you must log in.
Revision history for this message
Cristian Salamea (ovnicraft) wrote : Posted in a previous version of this proposal

Hello looks good but
+ 'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic account'),

is already necessary ?

Account invoice line gets by default this field.

Regards,

Revision history for this message
Alexis de Lattre (alexis-via) wrote : Posted in a previous version of this proposal

@Cristian
My merge proposal precisely consist in adding the analytic account on "invoice _tax_ lines". I know that this field in already present on "invoice lines".

Revision history for this message
Francois Degrave (fde-be) wrote : Posted in a previous version of this proposal

That is exactly what I planned to do. Too bad OpenERP has usually no interest in most external developer proposals :-(

Revision history for this message
Alexis de Lattre (alexis-via) wrote : Posted in a previous version of this proposal

@Francois Degrave
I'm very surprised to see an OpenERP S.A. employee saying this. I hope that OpenERP S.A. still has interest in proposals from external developers !! Otherwise, external contributors like me should move on to other free-software ERP projects :-(

Maybe you could help me "from the inside" to have this merge proposal reviewed, and I hope accepted. I am ready to answer all questions about it and make some changes if necessary. This merge proposal is motivated by real-life enterprise needs (Anevia in the present case).

Revision history for this message
Alexis de Lattre (alexis-via) wrote :

I have resumbmitted an new branch that is up-to-date with current addons-trunk. I have tested this new branch and it works well with trunk. The code itself has not been changed.

Unmerged revisions

7010. By Alexis de Lattre

Add analytic account on taxes and invoice tax lines.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'account/account.py'
2--- account/account.py 2012-06-26 20:09:09 +0000
3+++ account/account.py 2012-07-10 12:52:20 +0000
4@@ -1862,8 +1862,10 @@
5 'applicable_type': fields.selection( [('true','Always'), ('code','Given by Python Code')], 'Applicability', required=True,
6 help="If not applicable (computed through a Python code), the tax won't appear on the invoice."),
7 'domain':fields.char('Domain', size=32, help="This field is only used if you develop your own module allowing developers to create specific taxes in a custom domain."),
8- 'account_collected_id':fields.many2one('account.account', 'Invoice Tax Account'),
9- 'account_paid_id':fields.many2one('account.account', 'Refund Tax Account'),
10+ 'account_collected_id':fields.many2one('account.account', 'Invoice Tax Account', help="Set the account that will be set by default on invoice tax lines for invoices. Leave empty to use the expense account."),
11+ 'account_paid_id':fields.many2one('account.account', 'Refund Tax Account', help="Set the account that will be set by default on invoice tax lines for refunds. Leave empty to use the expense account."),
12+ 'account_analytic_collected_id':fields.many2one('account.analytic.account', 'Invoice Tax Analytic Account', help="Set the analytic account that will be used by default on the invoice tax lines for invoices. Leave empty if you don't want to use an analytic account on the invoice tax lines by default."),
13+ 'account_analytic_paid_id':fields.many2one('account.analytic.account', 'Refund Tax Analytic Account', help="Set the analytic account that will be used by default on the invoice tax lines for refunds. Leave empty if you don't want to use an analytic account on the invoice tax lines by default."),
14 'parent_id':fields.many2one('account.tax', 'Parent Tax Account', select=True),
15 'child_ids':fields.one2many('account.tax', 'parent_id', 'Child Tax Accounts'),
16 'child_depend':fields.boolean('Tax on Children', help="Set if the tax computation is based on the computation of child taxes rather than on the total amount."),
17@@ -2001,6 +2003,8 @@
18 'name':tax.description and tax.description + " - " + tax.name or tax.name,
19 'account_collected_id':tax.account_collected_id.id,
20 'account_paid_id':tax.account_paid_id.id,
21+ 'account_analytic_collected_id': tax.account_analytic_collected_id.id,
22+ 'account_analytic_paid_id': tax.account_analytic_paid_id.id,
23 'base_code_id': tax.base_code_id.id,
24 'ref_base_code_id': tax.ref_base_code_id.id,
25 'sequence': tax.sequence,
26@@ -2160,6 +2164,8 @@
27 'amount': amount,
28 'account_collected_id': tax.account_collected_id.id,
29 'account_paid_id': tax.account_paid_id.id,
30+ 'account_analytic_collected_id': tax.account_analytic_collected_id.id,
31+ 'account_analytic_paid_id': tax.account_analytic_paid_id.id,
32 'base_code_id': tax.base_code_id.id,
33 'ref_base_code_id': tax.ref_base_code_id.id,
34 'sequence': tax.sequence,
35
36=== modified file 'account/account_invoice.py'
37--- account/account_invoice.py 2012-06-01 12:15:47 +0000
38+++ account/account_invoice.py 2012-07-10 12:52:20 +0000
39@@ -756,7 +756,7 @@
40 for tax in inv.tax_line:
41 if tax.manual:
42 continue
43- key = (tax.tax_code_id.id, tax.base_code_id.id, tax.account_id.id)
44+ key = (tax.tax_code_id.id, tax.base_code_id.id, tax.account_id.id, tax.account_analytic_id.id)
45 tax_key.append(key)
46 if not key in compute_taxes:
47 raise osv.except_osv(_('Warning !'), _('Global taxes defined, but they are not in invoice lines !'))
48@@ -869,7 +869,7 @@
49 raise osv.except_osv(_('Error !'), _("Can not create the invoice !\nThe related payment term is probably misconfigured as it gives a computed amount greater than the total invoiced amount. The latest line of your payment term must be of type 'balance' to avoid rounding issues."))
50
51 # one move line per tax line
52- iml += ait_obj.move_line_get(cr, uid, inv.id)
53+ iml += ait_obj._get_analytic_lines(cr, uid, inv.id)
54
55 entry_type = ''
56 if inv.type in ('in_invoice', 'in_refund'):
57@@ -1578,6 +1578,7 @@
58 'invoice_id': fields.many2one('account.invoice', 'Invoice Line', ondelete='cascade', select=True),
59 'name': fields.char('Tax Description', size=64, required=True),
60 'account_id': fields.many2one('account.account', 'Tax Account', required=True, domain=[('type','<>','view'),('type','<>','income'), ('type', '<>', 'closed')]),
61+ 'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic account'),
62 'base': fields.float('Base', digits_compute=dp.get_precision('Account')),
63 'amount': fields.float('Amount', digits_compute=dp.get_precision('Account')),
64 'manual': fields.boolean('Manual'),
65@@ -1648,14 +1649,16 @@
66 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)
67 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)
68 val['account_id'] = tax['account_collected_id'] or line.account_id.id
69+ val['account_analytic_id'] = tax['account_analytic_collected_id']
70 else:
71 val['base_code_id'] = tax['ref_base_code_id']
72 val['tax_code_id'] = tax['ref_tax_code_id']
73 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)
74 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)
75 val['account_id'] = tax['account_paid_id'] or line.account_id.id
76+ val['account_analytic_id'] = tax['account_analytic_paid_id']
77
78- key = (val['tax_code_id'], val['base_code_id'], val['account_id'])
79+ key = (val['tax_code_id'], val['base_code_id'], val['account_id'], val['account_analytic_id'])
80 if not key in tax_grouped:
81 tax_grouped[key] = val
82 else:
83@@ -1671,6 +1674,44 @@
84 t['tax_amount'] = cur_obj.round(cr, uid, cur, t['tax_amount'])
85 return tax_grouped
86
87+
88+ def _get_analytic_lines(self, cr, uid, id, context=None):
89+ """Prepare the creation of tax account move lines and corresponding analytic lines.
90+ It is the equivalent of the function with the same name on the object account_invoice
91+ but for tax account move lines."""
92+ if context is None:
93+ context = {}
94+ inv_obj = self.pool.get('account.invoice')
95+ cur_obj = self.pool.get('res.currency')
96+ inv = inv_obj.browse(cr, uid, id, context=context)
97+
98+ company_currency = inv.company_id.currency_id.id
99+ if inv.type in ('out_invoice', 'in_refund'):
100+ sign = 1
101+ else:
102+ sign = -1
103+
104+ tax_lines = self.pool.get('account.invoice.tax').move_line_get(cr, uid, inv.id)
105+ for tl in tax_lines:
106+ if tl['account_analytic_id']:
107+ if inv.type in ('in_invoice', 'in_refund'):
108+ ref = inv.reference
109+ else:
110+ ref = inv_obj._convert_ref(cr, uid, inv.number)
111+ if not inv.journal_id.analytic_journal_id:
112+ raise osv.except_osv(_('No Analytic Journal !'),_("You have to define an analytic journal on the '%s' journal!") % (inv.journal_id.name,))
113+ tl['analytic_lines'] = [(0,0, {
114+ 'name': tl['name'],
115+ 'date': inv['date_invoice'],
116+ 'account_id': tl['account_analytic_id'],
117+ 'amount': cur_obj.compute(cr, uid, inv.currency_id.id, company_currency, tl['tax_amount'], context={'date': inv.date_invoice}) * sign,
118+ 'general_account_id': tl['account_id'],
119+ 'journal_id': inv.journal_id.analytic_journal_id.id,
120+ 'ref': ref,
121+ })]
122+ return tax_lines
123+
124+
125 def move_line_get(self, cr, uid, invoice_id):
126 res = []
127 cr.execute('SELECT * FROM account_invoice_tax WHERE invoice_id=%s', (invoice_id,))
128@@ -1687,7 +1728,8 @@
129 'price': t['amount'] or 0.0,
130 'account_id': t['account_id'],
131 'tax_code_id': t['tax_code_id'],
132- 'tax_amount': t['tax_amount']
133+ 'tax_amount': t['tax_amount'],
134+ 'account_analytic_id': t['account_analytic_id'],
135 })
136 return res
137
138
139=== modified file 'account/account_invoice_view.xml'
140--- account/account_invoice_view.xml 2012-07-03 12:41:11 +0000
141+++ account/account_invoice_view.xml 2012-07-10 12:52:20 +0000
142@@ -98,6 +98,7 @@
143 <field name="name"/>
144 <field name="sequence"/>
145 <field name="account_id" groups="account.group_account_user"/>
146+ <field name="account_analytic_id" domain="[('type','&lt;&gt;','view'), ('company_id', '=', parent.company_id), ('parent_id', '!=', False)]" groups="analytic.group_analytic_accounting" />
147 <field name="manual"/>
148 <field name="amount"/>
149 <field name="base" readonly="0"/>
150@@ -215,6 +216,7 @@
151 <tree editable="bottom" string="Taxes">
152 <field name="name"/>
153 <field name="account_id" groups="account.group_account_invoice"/>
154+ <field name="account_analytic_id" domain="[('type','&lt;&gt;','view'), ('company_id', '=', parent.company_id), ('parent_id', '!=', False)]" groups="analytic.group_analytic_accounting" />
155 <field name="base" on_change="base_change(base,parent.currency_id,parent.company_id,parent.date_invoice)" readonly="1"/>
156 <field name="amount" on_change="amount_change(amount,parent.currency_id,parent.company_id,parent.date_invoice)"/>
157
158
159=== modified file 'account/account_view.xml'
160--- account/account_view.xml 2012-07-02 11:27:50 +0000
161+++ account/account_view.xml 2012-07-10 12:52:20 +0000
162@@ -909,9 +909,9 @@
163 <field name="amount" attrs="{'readonly':[('type','in',('none', 'code', 'balance'))]}"/>
164 <separator colspan="4" string="Accounting Information"/>
165 <field name="account_collected_id" domain="[('type','&lt;&gt;','view'),('type','&lt;&gt;','consolidation')]"/>
166- <label colspan="2" nolabel="1" string="Keep empty to use the income account"/>
167+ <field name="account_analytic_collected_id" domain="[('type','&lt;&gt;','view'), ('company_id', '=', company_id), ('parent_id', '&lt;&gt;', False)]" groups="analytic.group_analytic_accounting" />
168 <field name="account_paid_id" domain="[('type','&lt;&gt;','view'),('type','&lt;&gt;','consolidation')]"/>
169- <label colspan="2" nolabel="1" string="Keep empty to use the expense account"/>
170+ <field name="account_analytic_paid_id" domain="[('type','&lt;&gt;','view'), ('company_id', '=', company_id), ('parent_id', '&lt;&gt;', False)]" groups="analytic.group_analytic_accounting" />
171 <separator colspan="4" string="Tax Declaration: Invoices"/>
172 <field name="base_code_id"/>
173 <field name="base_sign"/>

Subscribers

People subscribed via source and target branches

to all changes: