Merge lp:~elbati/openobject-italia/ref_l10n_it_withholding_tax into lp:~openobject-italia-core-devs/openobject-italia/italian-addons-6.1

Proposed by Lorenzo Battistini
Status: Merged
Merged at revision: 201
Proposed branch: lp:~elbati/openobject-italia/ref_l10n_it_withholding_tax
Merge into: lp:~openobject-italia-core-devs/openobject-italia/italian-addons-6.1
Diff against target: 276 lines (+174/-57)
3 files modified
l10n_it_withholding_tax/__openerp__.py (+19/-7)
l10n_it_withholding_tax/account.py (+104/-38)
l10n_it_withholding_tax/account_view.xml (+51/-12)
To merge this branch: bzr merge lp:~elbati/openobject-italia/ref_l10n_it_withholding_tax
Reviewer Review Type Date Requested Status
OpenERP Italia core devs Pending
Review via email: mp+116825@code.launchpad.net
To post a comment you must log in.
191. By Lorenzo Battistini

[FIX] l10n_it_withholding_tax
comment

192. By Lorenzo Battistini

[add] 'net pay' to invoice

193. By Lorenzo Battistini

[ref] entire workflow

194. By Lorenzo Battistini

[imp] description

195. By Lorenzo Battistini

[FIX] dont reconciled what reconciled yet

196. By Lorenzo Battistini

[fix] descr

197. By Lorenzo Battistini

[FIX] version

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'l10n_it_withholding_tax/__openerp__.py'
2--- l10n_it_withholding_tax/__openerp__.py 2012-07-03 06:22:49 +0000
3+++ l10n_it_withholding_tax/__openerp__.py 2012-08-09 13:32:07 +0000
4@@ -23,20 +23,32 @@
5 #
6 ##############################################################################
7 {
8- 'name': "Italian Localisation - Ritenute d'acconto",
9- 'version': '0.1',
10+ 'name': "Italian Localisation - Withholding tax",
11+ 'version': '0.2',
12 'category': 'Localisation/Italy',
13 'description': """
14- Modulo per le ritenute d'acconto sulle fatture fornitore
15-
16+Ritenute d'acconto sulle fatture fornitore
17+==========================================
18+
19+Per utilizzare il modulo bisogna configurare i campi associati alla company:
20+ - Termine di pagamento della ritenuta
21+ - Conto di debito per le ritenute da versare
22+ - Sezionale che conterrà le registrazioni legate alla ritenuta
23+
24+Durante la compilazione di una fattura fornitore con ritenuta d'acconto, l'utente dovrà specificare l'importo della ritenuta.
25+
26+Requisiti
27+---------
28+http://wiki.openerp-italia.org/doku.php/area_utente/requisiti/ritenuta_d_acconto
29+
30+Howto
31+-----
32 http://planet.domsense.com/2012/06/come-registrare-in-openerp-le-fatture-fornitore-con-ritenuta-dacconto/
33-
34- http://wiki.openerp-italia.org/doku.php/area_utente/requisiti/ritenuta_d_acconto
35 """,
36 'author': 'OpenERP Italian Community',
37 'website': 'http://www.openerp-italia.org',
38 'license': 'AGPL-3',
39- "depends" : ['account_invoice_template'],
40+ "depends" : ['account_invoice_template', 'account_voucher_cash_basis'],
41 "init_xml" : [
42 'account_view.xml',
43 ],
44
45=== modified file 'l10n_it_withholding_tax/account.py'
46--- l10n_it_withholding_tax/account.py 2012-06-12 15:40:54 +0000
47+++ l10n_it_withholding_tax/account.py 2012-08-09 13:32:07 +0000
48@@ -25,51 +25,117 @@
49
50 from osv import fields, osv
51 from tools.translate import _
52+import decimal_precision as dp
53
54-class account_tax(osv.osv):
55- _inherit = 'account.tax'
56+class res_company(osv.osv):
57+ _inherit = 'res.company'
58 _columns = {
59- 'withholding_tax': fields.boolean('Withholding Tax'),
60- 'withholding_payment_term_id': fields.many2one('account.payment.term', 'Withholding Payment Term'),
61+ 'withholding_payment_term_id': fields.many2one('account.payment.term', 'Withholding tax Payment Term'),
62+ 'withholding_account_id': fields.many2one('account.account','Withholding account', help='Payable account used for amount due to tax authority', domain=[('type', '=', 'payable')]),
63+ 'withholding_journal_id': fields.many2one('account.journal','Withholding journal', help="Journal used for registration of witholding amounts to be paid"),
64 }
65-account_tax()
66
67 class account_invoice(osv.osv):
68+
69+ def _net_pay(self, cr, uid, ids, field_name, arg, context=None):
70+ res = {}
71+ for invoice in self.browse(cr, uid, ids, context):
72+ res[invoice.id] = invoice.amount_total - invoice.withholding_amount
73+ return res
74+
75 _inherit = "account.invoice"
76-
77- def action_move_create(self, cr, uid, ids, context=None):
78- res = super(account_invoice, self).action_move_create(cr, uid, ids, context=context)
79+
80+ _columns = {
81+ 'withholding_amount': fields.float('Withholding amount', digits_compute=dp.get_precision('Account'), readonly=True, states={'draft':[('readonly',False)]}),
82+ 'has_withholding': fields.boolean('With withholding tax', readonly=True, states={'draft':[('readonly',False)]}),
83+ 'net_pay': fields.function(_net_pay, string="Net Pay"),
84+ }
85+
86+class account_voucher(osv.osv):
87+ _inherit = "account.voucher"
88+
89+ _columns = {
90+ 'withholding_move_ids': fields.many2many('account.move', 'voucher_withholding_move_rel', 'voucher_id', 'move_id', 'Withholding Tax Entries', readonly=True),
91+ }
92+
93+ def reconcile_withholding_move(self, cr, uid, invoice, wh_move, context=None):
94+ line_pool=self.pool.get('account.move.line')
95+ rec_ids = []
96+ for inv_move_line in invoice.move_id.line_id:
97+ if inv_move_line.account_id.type == 'payable' and not inv_move_line.reconcile_id:
98+ rec_ids.append(inv_move_line.id)
99+ for wh_line in wh_move.line_id:
100+ if wh_line.account_id.type == 'payable' and invoice.company_id.withholding_account_id and invoice.company_id.withholding_account_id.id != wh_line.account_id.id and not wh_line.reconcile_id:
101+ rec_ids.append(wh_line.id)
102+ return line_pool.reconcile_partial(cr, uid, rec_ids, type='auto', context=context)
103+
104+ def action_move_line_create(self, cr, uid, ids, context=None):
105+ res = super(account_voucher,self).action_move_line_create(cr, uid, ids, context)
106+ inv_pool = self.pool.get('account.invoice')
107+ move_pool = self.pool.get('account.move')
108 tax_pool = self.pool.get('account.tax')
109+ curr_pool = self.pool.get('res.currency')
110 term_pool = self.pool.get('account.payment.term')
111- for inv in self.browse(cr, uid, ids, context=context):
112- for move_line in inv.move_id.line_id:
113- if move_line.tax_code_id:
114- tax_ids = tax_pool.search(cr, uid, [('tax_code_id', '=', move_line.tax_code_id.id)])
115- is_withholding = False
116- for tax in tax_pool.browse(cr, uid, tax_ids):
117- if tax.withholding_tax:
118- is_withholding = True
119- if is_withholding:
120- if len(tax_ids) > 1:
121- raise osv.except_osv(_('Error'),
122- _('Too many taxes associated to tax.code %s') % move_line.tax_code_id.name)
123- if not tax_ids:
124- raise osv.except_osv(_('Error'),
125- _('No taxes associated to tax.code %s') % move_line.tax_code_id.name)
126- tax = tax_pool.browse(cr, uid, tax_ids[0])
127- if tax.withholding_tax and tax.withholding_payment_term_id:
128- due_list = term_pool.compute(
129- cr, uid, tax.withholding_payment_term_id.id, move_line.tax_amount,
130- date_ref=inv.date_invoice, context=context)
131- if len(due_list) > 1:
132- raise osv.except_osv(_('Error'),
133- _('The payment term %s has too many due dates')
134- % tax.withholding_payment_term_id.name)
135- if len(due_list) == 0:
136- raise osv.except_osv(_('Error'),
137- _('The payment term %s does not have due dates')
138- % tax.withholding_payment_term_id.name)
139- move_line.write({'date_maturity': due_list[0][0]})
140+ for voucher in self.browse(cr, uid, ids, context):
141+ amounts_by_invoice = super(account_voucher,self).allocated_amounts_grouped_by_invoice(cr, uid,voucher, context)
142+ for inv_id in amounts_by_invoice:
143+ invoice = inv_pool.browse(cr, uid, inv_id, context)
144+ if invoice.withholding_amount:
145+ # only for supplier payments
146+ if voucher.type != 'payment':
147+ raise osv.except_osv(_('Error'), _('Can\'t handle withholding tax with voucher of type other than payment'))
148+ if not invoice.company_id.withholding_account_id:
149+ raise osv.except_osv(_('Error'), _('The company does not have an associated Withholding account') )
150+ if not invoice.company_id.withholding_payment_term_id:
151+ raise osv.except_osv(_('Error'), _('The company does not have an associated Withholding Payment Term') )
152+ if not invoice.company_id.withholding_journal_id:
153+ raise osv.except_osv(_('Error'), _('The company does not have an associated Withholding journal') )
154+ # compute the new amount proportionally to paid amount
155+ new_line_amount = curr_pool.round(cr, uid, voucher.company_id.currency_id, ((amounts_by_invoice[invoice.id]['allocated'] + amounts_by_invoice[invoice.id]['write-off']) / invoice.net_pay) * invoice.withholding_amount)
156+
157+ # compute the due date
158+ due_list = term_pool.compute(
159+ cr, uid, invoice.company_id.withholding_payment_term_id.id, new_line_amount,
160+ date_ref=invoice.date_invoice, context=context)
161+ if len(due_list) > 1:
162+ raise osv.except_osv(_('Error'),
163+ _('The payment term %s has too many due dates')
164+ % invoice.company_id.withholding_payment_term_id.name)
165+ if len(due_list) == 0:
166+ raise osv.except_osv(_('Error'),
167+ _('The payment term %s does not have due dates')
168+ % invoice.company_id.withholding_payment_term_id.name)
169+
170+ new_move = {
171+ 'journal_id': invoice.company_id.withholding_journal_id.id,
172+ 'line_id': [
173+ (0,0,{
174+ 'name': invoice.number,
175+ 'account_id': invoice.account_id.id,
176+ 'debit': new_line_amount,
177+ 'credit': 0.0,
178+ }),
179+ (0,0,{
180+ 'name': _('Payable withholding - ') + invoice.number,
181+ 'account_id': invoice.company_id.withholding_account_id.id,
182+ 'debit': 0.0,
183+ 'credit': new_line_amount,
184+ 'date_maturity': due_list[0][0],
185+ }),
186+ ]
187+ }
188+ move_id = self.pool.get('account.move').create(cr, uid, new_move, context=context)
189+ self.reconcile_withholding_move(cr, uid, invoice, move_pool.browse(cr, uid, move_id, context), context)
190+ voucher.write({'withholding_move_ids': [(4, move_id)]})
191 return res
192
193-account_invoice()
194+ def cancel_voucher(self, cr, uid, ids, context=None):
195+ res = super(account_voucher,self).cancel_voucher(cr, uid, ids, context)
196+ reconcile_pool = self.pool.get('account.move.reconcile')
197+ move_pool = self.pool.get('account.move')
198+ for voucher in self.browse(cr, uid, ids, context=context):
199+ recs = []
200+ for move in voucher.withholding_move_ids:
201+ move_pool.button_cancel(cr, uid, [move.id])
202+ move_pool.unlink(cr, uid, [move.id])
203+ return res
204
205=== modified file 'l10n_it_withholding_tax/account_view.xml'
206--- l10n_it_withholding_tax/account_view.xml 2012-02-17 14:03:46 +0000
207+++ l10n_it_withholding_tax/account_view.xml 2012-08-09 13:32:07 +0000
208@@ -2,17 +2,56 @@
209 <openerp>
210 <data>
211
212- <record id="view_tax_form" model="ir.ui.view">
213- <field name="name">account.tax.form</field>
214- <field name="model">account.tax</field>
215- <field name="type">form</field>
216- <field name="inherit_id" ref="account.view_tax_form"></field>
217- <field name="arch" type="xml">
218- <field name="active" position="after">
219- <field name="withholding_tax"/>
220- <field name="withholding_payment_term_id" attrs="{'readonly':[('withholding_tax','=',False)]}"/>
221- </field>
222- </field>
223- </record>
224+<!-- company -->
225+
226+ <record model="ir.ui.view" id="view_company_inherit_form">
227+ <field name="name">res.company.form.inherit</field>
228+ <field name="inherit_id" ref="account.view_company_inherit_form"/>
229+ <field name="model">res.company</field>
230+ <field name="type">form</field>
231+ <field name="arch" type="xml">
232+ <field name="paypal_account" position="after">
233+ <separator colspan="4"></separator>
234+ <field name="withholding_payment_term_id"/>
235+ <field name="withholding_account_id"/>
236+ <field name="withholding_journal_id" />
237+ <separator colspan="4"></separator>
238+ </field>
239+ </field>
240+ </record>
241+
242+ <!-- invoice -->
243+
244+ <record id="invoice_supplier_form" model="ir.ui.view">
245+ <field name="name">account.invoice.supplier.form</field>
246+ <field name="model">account.invoice</field>
247+ <field name="type">form</field>
248+ <field name="inherit_id" ref="account.invoice_supplier_form"/>
249+ <field name="arch" type="xml">
250+ <field name="date_due" position="after">
251+ <field name="has_withholding"/>
252+ </field>
253+ <field name="amount_total" position="after">
254+ <field name="withholding_amount" attrs="{'invisible': [('has_withholding', '=', False)]}"/>
255+ <field name="net_pay" attrs="{'invisible': [('has_withholding', '=', False)]}"/>
256+ </field>
257+ </field>
258+ </record>
259+
260+ <!-- voucher -->
261+
262+ <record id="view_vendor_payment_form_wh_move" model="ir.ui.view">
263+ <field name="name">account.voucher.payment.form.wh.move</field>
264+ <field name="model">account.voucher</field>
265+ <field name="type">form</field>
266+ <field name="inherit_id" ref="account_voucher.view_vendor_payment_form"/>
267+ <field name="arch" type="xml">
268+ <field name="move_ids" position="after">
269+ <separator string="Withholding tax entries" colspan="4"></separator>
270+ <field name="withholding_move_ids" colspan="4" nolabel="1"/>
271+ </field>
272+ </field>
273+ </record>
274+
275 </data>
276 </openerp>

Subscribers

People subscribed via source and target branches