Merge lp:~openbig/bigconsulting/changes_account_invoice_cash_discount into lp:bigconsulting
- changes_account_invoice_cash_discount
- Merge into addons
Proposed by
gpa(OpenERP)
Status: | Merged |
---|---|
Merged at revision: | 9 |
Proposed branch: | lp:~openbig/bigconsulting/changes_account_invoice_cash_discount |
Merge into: | lp:bigconsulting |
Diff against target: |
619 lines (+327/-213) 8 files modified
account_invoice_cash_discount/__terp__.py (+1/-1) account_invoice_cash_discount/account_invoice_cash_discount.py (+36/-2) account_invoice_cash_discount/account_invoice_cash_discount_view.xml (+2/-0) account_invoice_cash_discount/account_wizard.xml (+0/-6) account_invoice_cash_discount/wizard/__init__.py (+1/-1) account_invoice_cash_discount/wizard/account_pay_invoice.py (+224/-0) account_invoice_cash_discount/wizard/account_pay_invoice_view.xml (+63/-0) account_invoice_cash_discount/wizard/wizard_pay_invoice.py (+0/-203) |
To merge this branch: | bzr merge lp:~openbig/bigconsulting/changes_account_invoice_cash_discount |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
openbig | Pending | ||
Review via email: mp+26461@code.launchpad.net |
Commit message
Description of the change
convert wizard pay invoice to osv memroy wizard make onchange on Amount Paid field
To post a comment you must log in.
- 10. By gpa(OpenERP)
-
changes on account_
invoice_ cash_discount
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'account_invoice_cash_discount/__terp__.py' | |||
2 | --- account_invoice_cash_discount/__terp__.py 2010-05-28 10:52:25 +0000 | |||
3 | +++ account_invoice_cash_discount/__terp__.py 2010-06-01 08:53:22 +0000 | |||
4 | @@ -35,7 +35,7 @@ | |||
5 | 35 | ], | 35 | ], |
6 | 36 | "update_xml" : [ | 36 | "update_xml" : [ |
7 | 37 | "account_invoice_cash_discount_view.xml", | 37 | "account_invoice_cash_discount_view.xml", |
9 | 38 | "account_wizard.xml" | 38 | 'wizard/account_pay_invoice_view.xml', |
10 | 39 | ], | 39 | ], |
11 | 40 | "active": False, | 40 | "active": False, |
12 | 41 | "installable": True, | 41 | "installable": True, |
13 | 42 | 42 | ||
14 | === modified file 'account_invoice_cash_discount/account_invoice_cash_discount.py' | |||
15 | --- account_invoice_cash_discount/account_invoice_cash_discount.py 2010-05-28 10:52:25 +0000 | |||
16 | +++ account_invoice_cash_discount/account_invoice_cash_discount.py 2010-06-01 08:53:22 +0000 | |||
17 | @@ -49,8 +49,10 @@ | |||
18 | 49 | _inherit = "account.invoice" | 49 | _inherit = "account.invoice" |
19 | 50 | 50 | ||
20 | 51 | def _get_payment(self, cr, uid, ids, resudial_amonut, payment_term, context=None): | 51 | def _get_payment(self, cr, uid, ids, resudial_amonut, payment_term, context=None): |
23 | 52 | 52 | """ | |
24 | 53 | #This function used to count the discount payment term | 53 | This function return the Discount according to the payment term cash discount term |
25 | 54 | """ | ||
26 | 55 | |||
27 | 54 | if context is None: | 56 | if context is None: |
28 | 55 | context = {} | 57 | context = {} |
29 | 56 | 58 | ||
30 | @@ -88,6 +90,38 @@ | |||
31 | 88 | ted +=rr | 90 | ted +=rr |
32 | 89 | discunt = res + ted | 91 | discunt = res + ted |
33 | 90 | return discunt | 92 | return discunt |
34 | 93 | |||
35 | 94 | def _get_account(self, cr, uid, ids, resudial_amonut, payment_term, context=None): | ||
36 | 95 | """ | ||
37 | 96 | This function return the Account according to the payment term cash discount term | ||
38 | 97 | """ | ||
39 | 98 | if context is None: | ||
40 | 99 | context = {} | ||
41 | 100 | |||
42 | 101 | tax_obj = self.pool.get('account.tax') | ||
43 | 102 | invoice = self.browse(cr, uid, ids[0], context=context) | ||
44 | 103 | |||
45 | 104 | if invoice.date_due: | ||
46 | 105 | date1 = invoice.date_due | ||
47 | 106 | else: | ||
48 | 107 | date1 = time.strftime('%Y-%m-%d') | ||
49 | 108 | |||
50 | 109 | if 'date_p' in context and context['date_p']: | ||
51 | 110 | date2 = context['date_p'] | ||
52 | 111 | else: | ||
53 | 112 | date2 = time.strftime('%Y-%m-%d') | ||
54 | 113 | |||
55 | 114 | from_dt = time.mktime(time.strptime(date1,'%Y-%m-%d')) | ||
56 | 115 | to_dt = time.mktime(time.strptime(date2,'%Y-%m-%d')) | ||
57 | 116 | diff_day = (from_dt-to_dt)/(3600*24) | ||
58 | 117 | if payment_term: | ||
59 | 118 | pt = self.pool.get('account.payment.term').browse(cr, uid, payment_term, context=context) | ||
60 | 119 | if pt.cash_discount_ids: | ||
61 | 120 | res = 0.0 | ||
62 | 121 | for d in pt.cash_discount_ids: | ||
63 | 122 | if diff_day == d.delay or diff_day < d.delay: | ||
64 | 123 | account_id = d.discount_account_id.id | ||
65 | 124 | return account_id | ||
66 | 91 | 125 | ||
67 | 92 | def pay_and_reconcile(self, cr, uid, ids, pay_amount, pay_account_id, period_id, pay_journal_id, writeoff_acc_id, writeoff_period_id, writeoff_journal_id, context=None, name=''): | 126 | def pay_and_reconcile(self, cr, uid, ids, pay_amount, pay_account_id, period_id, pay_journal_id, writeoff_acc_id, writeoff_period_id, writeoff_journal_id, context=None, name=''): |
68 | 93 | 127 | ||
69 | 94 | 128 | ||
70 | === modified file 'account_invoice_cash_discount/account_invoice_cash_discount_view.xml' | |||
71 | --- account_invoice_cash_discount/account_invoice_cash_discount_view.xml 2010-05-26 13:32:15 +0000 | |||
72 | +++ account_invoice_cash_discount/account_invoice_cash_discount_view.xml 2010-06-01 08:53:22 +0000 | |||
73 | @@ -14,6 +14,7 @@ | |||
74 | 14 | <field name="name" select="1"/> | 14 | <field name="name" select="1"/> |
75 | 15 | <field name="delay" select="1"/> | 15 | <field name="delay" select="1"/> |
76 | 16 | <field name="discount" select="1"/> | 16 | <field name="discount" select="1"/> |
77 | 17 | <field name="discount_account_id" /> | ||
78 | 17 | </form> | 18 | </form> |
79 | 18 | </field> | 19 | </field> |
80 | 19 | </record> | 20 | </record> |
81 | @@ -27,6 +28,7 @@ | |||
82 | 27 | <field name="name" select="1"/> | 28 | <field name="name" select="1"/> |
83 | 28 | <field name="delay" select="1"/> | 29 | <field name="delay" select="1"/> |
84 | 29 | <field name="discount" select="1"/> | 30 | <field name="discount" select="1"/> |
85 | 31 | <field name="discount_account_id" /> | ||
86 | 30 | </tree> | 32 | </tree> |
87 | 31 | </field> | 33 | </field> |
88 | 32 | </record> | 34 | </record> |
89 | 33 | 35 | ||
90 | === removed file 'account_invoice_cash_discount/account_wizard.xml' | |||
91 | --- account_invoice_cash_discount/account_wizard.xml 2010-05-26 13:32:15 +0000 | |||
92 | +++ account_invoice_cash_discount/account_wizard.xml 1970-01-01 00:00:00 +0000 | |||
93 | @@ -1,6 +0,0 @@ | |||
94 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
95 | 2 | <openerp> | ||
96 | 3 | <data> | ||
97 | 4 | <wizard id="wizard_invoice_pay" model="account.invoice" name="account.invoice.pay1" string="Pay invoice" groups="base.group_user"/> | ||
98 | 5 | </data> | ||
99 | 6 | </openerp> | ||
100 | 7 | 0 | ||
101 | === modified file 'account_invoice_cash_discount/wizard/__init__.py' | |||
102 | --- account_invoice_cash_discount/wizard/__init__.py 2010-05-26 13:32:15 +0000 | |||
103 | +++ account_invoice_cash_discount/wizard/__init__.py 2010-06-01 08:53:22 +0000 | |||
104 | @@ -20,7 +20,7 @@ | |||
105 | 20 | # | 20 | # |
106 | 21 | ############################################################################## | 21 | ############################################################################## |
107 | 22 | 22 | ||
109 | 23 | import wizard_pay_invoice | 23 | import account_pay_invoice |
110 | 24 | 24 | ||
111 | 25 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | 25 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
112 | 26 | 26 | ||
113 | 27 | 27 | ||
114 | === added file 'account_invoice_cash_discount/wizard/account_pay_invoice.py' | |||
115 | --- account_invoice_cash_discount/wizard/account_pay_invoice.py 1970-01-01 00:00:00 +0000 | |||
116 | +++ account_invoice_cash_discount/wizard/account_pay_invoice.py 2010-06-01 08:53:22 +0000 | |||
117 | @@ -0,0 +1,224 @@ | |||
118 | 1 | # -*- coding: utf-8 -*- | ||
119 | 2 | ############################################################################## | ||
120 | 3 | # | ||
121 | 4 | # OpenERP, Open Source Management Solution | ||
122 | 5 | # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). | ||
123 | 6 | # | ||
124 | 7 | # This program is free software: you can redistribute it and/or modify | ||
125 | 8 | # it under the terms of the GNU Affero General Public License as | ||
126 | 9 | # published by the Free Software Foundation, either version 3 of the | ||
127 | 10 | # License, or (at your option) any later version. | ||
128 | 11 | # | ||
129 | 12 | # This program is distributed in the hope that it will be useful, | ||
130 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
131 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
132 | 15 | # GNU Affero General Public License for more details. | ||
133 | 16 | # | ||
134 | 17 | # You should have received a copy of the GNU Affero General Public License | ||
135 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
136 | 19 | # | ||
137 | 20 | ############################################################################## | ||
138 | 21 | import time | ||
139 | 22 | |||
140 | 23 | from osv import fields, osv | ||
141 | 24 | from tools.translate import _ | ||
142 | 25 | #import decimal_precision as dp | ||
143 | 26 | |||
144 | 27 | class account_invoice_pay_writeoff(osv.osv_memory): | ||
145 | 28 | """ | ||
146 | 29 | Opens the write off amount pay form. | ||
147 | 30 | """ | ||
148 | 31 | _name = "account.invoice.pay.writeoff" | ||
149 | 32 | _description = "Pay Invoice " | ||
150 | 33 | _columns = { | ||
151 | 34 | 'writeoff_acc_id': fields.many2one('account.account', 'Write-Off account', required=True), | ||
152 | 35 | 'writeoff_journal_id': fields.many2one('account.journal', 'Write-Off journal', required=True), | ||
153 | 36 | 'comment': fields.char('Comment', size=64, required=True), | ||
154 | 37 | 'analytic_id': fields.many2one('account.analytic.account','Analytic Account'), | ||
155 | 38 | } | ||
156 | 39 | _defaults = { | ||
157 | 40 | 'comment': 'Write-Off', | ||
158 | 41 | } | ||
159 | 42 | |||
160 | 43 | def pay_and_reconcile_writeoff(self, cr, uid, ids, context=None): | ||
161 | 44 | data = self.read(cr, uid, ids,context=context)[0] | ||
162 | 45 | context.update({'write_off':data}) | ||
163 | 46 | self.pool.get('account.invoice.pay').pay_and_reconcile(cr, uid, ids, context=context) | ||
164 | 47 | return {} | ||
165 | 48 | |||
166 | 49 | account_invoice_pay_writeoff() | ||
167 | 50 | |||
168 | 51 | class account_invoice_pay(osv.osv_memory): | ||
169 | 52 | """ | ||
170 | 53 | Generate pay invoice wizard, user can make partial or full payment for invoice. | ||
171 | 54 | """ | ||
172 | 55 | _name = "account.invoice.pay" | ||
173 | 56 | _description = "Pay Invoice " | ||
174 | 57 | _columns = { | ||
175 | 58 | 'amount': fields.float('Amount paid', required=True), | ||
176 | 59 | 'name': fields.char('Entry Name', size=64, required=True), | ||
177 | 60 | 'date': fields.date('Date payment', required=True), | ||
178 | 61 | 'journal_id': fields.many2one('account.journal', 'Journal/Payment Mode', required=True), | ||
179 | 62 | 'period_id': fields.many2one('account.period', 'Period', required=True), | ||
180 | 63 | 'cash_amount':fields.float('Cash Discount Amount', required=True), | ||
181 | 64 | 'account_id': fields.many2one('account.account', 'Account For Discount', required=True), | ||
182 | 65 | } | ||
183 | 66 | |||
184 | 67 | def view_init(self, cr, uid, ids, context=None): | ||
185 | 68 | invoice = self.pool.get('account.invoice').browse(cr, uid, context['active_id'], context=context) | ||
186 | 69 | if invoice.state in ['draft', 'proforma2', 'cancel']: | ||
187 | 70 | raise osv.except_osv(_('Error !'), _('Can not pay draft/proforma/cancel invoice.')) | ||
188 | 71 | pass | ||
189 | 72 | |||
190 | 73 | def _get_period(self, cr, uid, context=None): | ||
191 | 74 | ids = self.pool.get('account.period').find(cr, uid, context=context) | ||
192 | 75 | period_id = False | ||
193 | 76 | if len(ids): | ||
194 | 77 | period_id = ids[0] | ||
195 | 78 | return period_id | ||
196 | 79 | |||
197 | 80 | def _get_amount(self, cr, uid, context=None): | ||
198 | 81 | return self.pool.get('account.invoice').browse(cr, uid, context['id'], context=context).residual | ||
199 | 82 | |||
200 | 83 | def on_change_ammount(self, cr, uid, ids, amount, context=None): | ||
201 | 84 | """ | ||
202 | 85 | Function return the Discount according to the Amount paid and Payment Term Cash Discount | ||
203 | 86 | """ | ||
204 | 87 | res = {} | ||
205 | 88 | obj_inv = self.pool.get('account.invoice') | ||
206 | 89 | invoice = obj_inv.browse(cr, uid, context['id'], context=context) | ||
207 | 90 | discount = obj_inv._get_payment(cr, uid, [context['id']] , amount, invoice.payment_term.id, context=context) | ||
208 | 91 | return {'value' : {'cash_amount':discount}} | ||
209 | 92 | |||
210 | 93 | def _get_discount(self, cr, uid, context=None): | ||
211 | 94 | obj_inv = self.pool.get('account.invoice') | ||
212 | 95 | invoice = obj_inv.browse(cr, uid, context['id'], context=context) | ||
213 | 96 | discount = obj_inv._get_payment(cr, uid, [context['id']] , invoice.residual, invoice.payment_term.id, context=context) | ||
214 | 97 | return discount | ||
215 | 98 | |||
216 | 99 | def _get_account(self, cr, uid, context=None): | ||
217 | 100 | """ | ||
218 | 101 | This function return the Account according to the payment term cash term and map the account with fiscal position | ||
219 | 102 | """ | ||
220 | 103 | obj_inv = self.pool.get('account.invoice') | ||
221 | 104 | invoice = obj_inv.browse(cr, uid, context['id'], context=context) | ||
222 | 105 | account = obj_inv._get_account(cr, uid, [context['id']] , invoice.residual, invoice.payment_term.id, context=context) | ||
223 | 106 | fpos = invoice.fiscal_position or False | ||
224 | 107 | account = self.pool.get('account.fiscal.position').map_account(cr, uid, fpos, account) | ||
225 | 108 | return account | ||
226 | 109 | |||
227 | 110 | _defaults = { | ||
228 | 111 | 'date': lambda *a: time.strftime('%Y-%m-%d'), | ||
229 | 112 | 'period_id': _get_period, | ||
230 | 113 | 'amount': _get_amount, | ||
231 | 114 | 'cash_amount':_get_discount, | ||
232 | 115 | 'account_id':_get_account | ||
233 | 116 | } | ||
234 | 117 | |||
235 | 118 | def wo_check(self, cr, uid, ids, context=None): | ||
236 | 119 | cur_obj = self.pool.get('res.currency') | ||
237 | 120 | mod_obj = self.pool.get('ir.model.data') | ||
238 | 121 | if context is None: | ||
239 | 122 | context = {} | ||
240 | 123 | data = self.read(cr, uid, ids,context=context)[0] | ||
241 | 124 | invoice = self.pool.get('account.invoice').browse(cr, uid, context['id'], context) | ||
242 | 125 | journal = self.pool.get('account.journal').browse(cr, uid, data['journal_id'], context) | ||
243 | 126 | |||
244 | 127 | # Here we need that: | ||
245 | 128 | # The invoice total amount in company's currency <> paid amount in company currency | ||
246 | 129 | # (according to the correct day rate, invoicing rate and payment rate are may be different) | ||
247 | 130 | # => Ask to a write-off of the difference. This could happen even if both amount are equal, | ||
248 | 131 | # because if the currency rate | ||
249 | 132 | # Get the amount in company currency for the invoice (according to move lines) | ||
250 | 133 | inv_amount_company_currency = 0 | ||
251 | 134 | for aml in invoice.move_id.line_id: | ||
252 | 135 | if aml.account_id.id == invoice.account_id.id or aml.account_id.type in ('receivable', 'payable'): | ||
253 | 136 | inv_amount_company_currency += aml.debit | ||
254 | 137 | inv_amount_company_currency -= aml.credit | ||
255 | 138 | inv_amount_company_currency = abs(inv_amount_company_currency) | ||
256 | 139 | |||
257 | 140 | # Get the current amount paid in company currency | ||
258 | 141 | if journal.currency and invoice.company_id.currency_id.id<>journal.currency.id: | ||
259 | 142 | ctx = {'date':data['date']} | ||
260 | 143 | amount_paid = cur_obj.compute(cr, uid, journal.currency.id, invoice.company_id.currency_id.id, data['amount'], round=True, context=ctx) | ||
261 | 144 | else: | ||
262 | 145 | amount_paid = data['amount'] | ||
263 | 146 | # Get the old payment if there are some | ||
264 | 147 | if invoice.payment_ids: | ||
265 | 148 | debit=credit=0.0 | ||
266 | 149 | for payment in invoice.payment_ids: | ||
267 | 150 | debit+=payment.debit | ||
268 | 151 | credit+=payment.credit | ||
269 | 152 | amount_paid+=abs(debit-credit) | ||
270 | 153 | |||
271 | 154 | # Test if there is a difference according to currency rouding setting | ||
272 | 155 | if self.pool.get('res.currency').is_zero(cr, uid, invoice.company_id.currency_id, | ||
273 | 156 | (amount_paid - inv_amount_company_currency)): | ||
274 | 157 | return self.pay_and_reconcile(cr, uid, ids, context=context) | ||
275 | 158 | else: | ||
276 | 159 | model_data_ids = mod_obj.search(cr, uid,[('model','=','ir.ui.view'),('name','=','view_account_invoice_pay_writeoff')], context=context) | ||
277 | 160 | resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id'] | ||
278 | 161 | return { | ||
279 | 162 | 'name': _('Information addendum'), | ||
280 | 163 | 'context': context, | ||
281 | 164 | 'view_type': 'form', | ||
282 | 165 | 'view_mode': 'form', | ||
283 | 166 | 'res_model': 'account.invoice.pay.writeoff', | ||
284 | 167 | 'views': [(resource_id,'form')], | ||
285 | 168 | 'type': 'ir.actions.act_window', | ||
286 | 169 | 'target': 'new', | ||
287 | 170 | } | ||
288 | 171 | |||
289 | 172 | def pay_and_reconcile(self, cr, uid, ids, context=None): | ||
290 | 173 | cur_obj = self.pool.get('res.currency') | ||
291 | 174 | if context is None: | ||
292 | 175 | context = {} | ||
293 | 176 | data = self.read(cr, uid, ids,context=context)[0] | ||
294 | 177 | writeoff_account_id = False | ||
295 | 178 | writeoff_journal_id = False | ||
296 | 179 | comment = False | ||
297 | 180 | |||
298 | 181 | if 'write_off' in context and context['write_off'] : | ||
299 | 182 | writeoff_account_id = context['write_off']['writeoff_acc_id'] | ||
300 | 183 | writeoff_journal_id = context['write_off']['writeoff_journal_id'] | ||
301 | 184 | comment = context['write_off']['comment'] | ||
302 | 185 | |||
303 | 186 | amount = data['amount'] | ||
304 | 187 | |||
305 | 188 | invoice = self.pool.get('account.invoice').browse(cr, uid, context['id'], context=context) | ||
306 | 189 | journal = self.pool.get('account.journal').browse(cr, uid, data['journal_id'], context=context) | ||
307 | 190 | # Compute the amount in company's currency, with the journal currency (which is equal to payment currency) | ||
308 | 191 | # when it is needed : If payment currency (according to selected journal.currency) is <> from company currency | ||
309 | 192 | if journal.currency and invoice.company_id.currency_id.id<>journal.currency.id: | ||
310 | 193 | ctx = {'date':data['date']} | ||
311 | 194 | amount = cur_obj.compute(cr, uid, journal.currency.id, invoice.company_id.currency_id.id, amount, context=ctx) | ||
312 | 195 | currency_id = journal.currency.id | ||
313 | 196 | # Put the paid amount in currency, and the currency, in the context if currency is different from company's currency | ||
314 | 197 | context.update({'amount_currency':data['amount'],'currency_id':currency_id}) | ||
315 | 198 | |||
316 | 199 | if invoice.company_id.currency_id.id<>invoice.currency_id.id: | ||
317 | 200 | ctx = {'date':data['date']} | ||
318 | 201 | amount = cur_obj.compute(cr, uid, invoice.currency_id.id, invoice.company_id.currency_id.id, amount, context=ctx) | ||
319 | 202 | currency_id = invoice.currency_id.id | ||
320 | 203 | # Put the paid amount in currency, and the currency, in the context if currency is different from company's currency | ||
321 | 204 | context.update({'amount_currency':data['amount'],'currency_id':currency_id}) | ||
322 | 205 | |||
323 | 206 | # Take the choosen date | ||
324 | 207 | if comment: | ||
325 | 208 | context.update({'date_p':data['date'],'comment':comment}) | ||
326 | 209 | else: | ||
327 | 210 | context.update({'date_p':data['date'],'comment':False}) | ||
328 | 211 | |||
329 | 212 | context.update({'account_id':data['account_id'],'cash_amount':data['cash_amount'],'amount_currency':data['amount']}) | ||
330 | 213 | |||
331 | 214 | acc_id = journal.default_credit_account_id and journal.default_credit_account_id.id | ||
332 | 215 | if not acc_id: | ||
333 | 216 | raise osv.except_osv(_('Error !'), _('Your journal must have a default credit and debit account.')) | ||
334 | 217 | self.pool.get('account.invoice').pay_and_reconcile(cr, uid, [context['id']], | ||
335 | 218 | amount, acc_id, data['period_id'], data['journal_id'], writeoff_account_id, | ||
336 | 219 | data['period_id'], writeoff_journal_id, context, data['name']) | ||
337 | 220 | return {} | ||
338 | 221 | |||
339 | 222 | account_invoice_pay() | ||
340 | 223 | |||
341 | 224 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
342 | 0 | \ No newline at end of file | 225 | \ No newline at end of file |
343 | 1 | 226 | ||
344 | === added file 'account_invoice_cash_discount/wizard/account_pay_invoice_view.xml' | |||
345 | --- account_invoice_cash_discount/wizard/account_pay_invoice_view.xml 1970-01-01 00:00:00 +0000 | |||
346 | +++ account_invoice_cash_discount/wizard/account_pay_invoice_view.xml 2010-06-01 08:53:22 +0000 | |||
347 | @@ -0,0 +1,63 @@ | |||
348 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
349 | 2 | <openerp> | ||
350 | 3 | <data> | ||
351 | 4 | <record id="view_account_invoice_pay" model="ir.ui.view"> | ||
352 | 5 | <field name="name">account.invoice.pay.form</field> | ||
353 | 6 | <field name="model">account.invoice.pay</field> | ||
354 | 7 | <field name="type">form</field> | ||
355 | 8 | <field name="arch" type="xml"> | ||
356 | 9 | <form string="Pay invoice"> | ||
357 | 10 | <group colspan="4" > | ||
358 | 11 | <field name="amount" on_change="on_change_ammount(amount,context)"/> | ||
359 | 12 | <newline/> | ||
360 | 13 | <field name="name"/> | ||
361 | 14 | <field name="date"/> | ||
362 | 15 | <field name="journal_id"/> | ||
363 | 16 | <field name="period_id"/> | ||
364 | 17 | <field name="cash_amount"/> | ||
365 | 18 | <field name="account_id"/> | ||
366 | 19 | </group> | ||
367 | 20 | <group colspan="4" col="6"> | ||
368 | 21 | <label string ="" colspan="2"/> | ||
369 | 22 | <button icon="gtk-cancel" special="cancel" string="Cancel"/> | ||
370 | 23 | <button icon="gtk-execute" string="Partial Payment" name="pay_and_reconcile" type="object"/> | ||
371 | 24 | <button icon="gtk-execute" string="Full Payment" name="wo_check" type="object"/> | ||
372 | 25 | </group> | ||
373 | 26 | </form> | ||
374 | 27 | </field> | ||
375 | 28 | </record> | ||
376 | 29 | |||
377 | 30 | <act_window name="Pay Invoice" | ||
378 | 31 | res_model="account.invoice.pay" | ||
379 | 32 | src_model="account.invoice" | ||
380 | 33 | view_mode="form" | ||
381 | 34 | target="new" | ||
382 | 35 | context="{'id': active_id}" | ||
383 | 36 | id="action_view_account_invoice_pay"/> | ||
384 | 37 | |||
385 | 38 | <record id="view_account_invoice_pay_writeoff" model="ir.ui.view"> | ||
386 | 39 | <field name="name">account.invoice.pay.writeoff.form</field> | ||
387 | 40 | <field name="model">account.invoice.pay.writeoff</field> | ||
388 | 41 | <field name="type">form</field> | ||
389 | 42 | <field name="arch" type="xml"> | ||
390 | 43 | <form string="Information addendum"> | ||
391 | 44 | <group colspan="4" > | ||
392 | 45 | <separator string="Write-Off Move" colspan="4"/> | ||
393 | 46 | <field name="writeoff_journal_id"/> | ||
394 | 47 | <field name="writeoff_acc_id" domain="[('type','<>','view'),('type','<>','consolidation')]"/> | ||
395 | 48 | <field name="comment"/> | ||
396 | 49 | <separator string="Analytic" colspan="4"/> | ||
397 | 50 | <field name="analytic_id"/> | ||
398 | 51 | </group> | ||
399 | 52 | <group colspan="4" col="6"> | ||
400 | 53 | <label string ="" colspan="2"/> | ||
401 | 54 | <button icon="gtk-cancel" special="cancel" string="Cancel"/> | ||
402 | 55 | <button icon="gtk-execute" string="Pay and reconcile" name="pay_and_reconcile_writeoff" type="object"/> | ||
403 | 56 | </group> | ||
404 | 57 | </form> | ||
405 | 58 | </field> | ||
406 | 59 | </record> | ||
407 | 60 | |||
408 | 61 | |||
409 | 62 | </data> | ||
410 | 63 | </openerp> | ||
411 | 0 | \ No newline at end of file | 64 | \ No newline at end of file |
412 | 1 | 65 | ||
413 | === removed file 'account_invoice_cash_discount/wizard/wizard_pay_invoice.py' | |||
414 | --- account_invoice_cash_discount/wizard/wizard_pay_invoice.py 2010-05-27 07:24:45 +0000 | |||
415 | +++ account_invoice_cash_discount/wizard/wizard_pay_invoice.py 1970-01-01 00:00:00 +0000 | |||
416 | @@ -1,203 +0,0 @@ | |||
417 | 1 | # -*- encoding: utf-8 -*- | ||
418 | 2 | ############################################################################## | ||
419 | 3 | # | ||
420 | 4 | # OpenERP, Open Source Management Solution | ||
421 | 5 | # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved | ||
422 | 6 | # $Id$ | ||
423 | 7 | # | ||
424 | 8 | # This program is free software: you can redistribute it and/or modify | ||
425 | 9 | # it under the terms of the GNU General Public License as published by | ||
426 | 10 | # the Free Software Foundation, either version 3 of the License, or | ||
427 | 11 | # (at your option) any later version. | ||
428 | 12 | # | ||
429 | 13 | # This program is distributed in the hope that it will be useful, | ||
430 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
431 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
432 | 16 | # GNU General Public License for more details. | ||
433 | 17 | # | ||
434 | 18 | # You should have received a copy of the GNU General Public License | ||
435 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
436 | 20 | # | ||
437 | 21 | ############################################################################## | ||
438 | 22 | |||
439 | 23 | import wizard | ||
440 | 24 | import pooler | ||
441 | 25 | import time | ||
442 | 26 | from tools.translate import _ | ||
443 | 27 | import tools | ||
444 | 28 | |||
445 | 29 | pay_form = '''<?xml version="1.0"?> | ||
446 | 30 | <form string="Pay invoice"> | ||
447 | 31 | <field name="amount"/> | ||
448 | 32 | <newline/> | ||
449 | 33 | <field name="name"/> | ||
450 | 34 | <field name="date"/> | ||
451 | 35 | <field name="journal_id"/> | ||
452 | 36 | <field name="period_id"/> | ||
453 | 37 | <field name="cash_amount"/> | ||
454 | 38 | <field name="account_id"/> | ||
455 | 39 | </form>''' | ||
456 | 40 | |||
457 | 41 | pay_fields = { | ||
458 | 42 | 'amount': {'string': 'Amount paid', 'type':'float', 'required':True, 'digits': (16,int(tools.config['price_accuracy']))}, | ||
459 | 43 | 'name': {'string': 'Entry Name', 'type':'char', 'size': 64, 'required':True}, | ||
460 | 44 | 'cash_amount': {'string': 'Cash Discount Amount', 'type':'float', 'required':True, 'digits': (16,int(tools.config['price_accuracy']))}, | ||
461 | 45 | 'account_id': {'string': 'Account For Discount', 'type': 'many2one', 'relation':'account.account', 'required':True}, | ||
462 | 46 | 'date': {'string': 'Payment date', 'type':'date', 'required':True, 'default':lambda *args: time.strftime('%Y-%m-%d')}, | ||
463 | 47 | 'journal_id': {'string': 'Journal/Payment Mode', 'type': 'many2one', 'relation':'account.journal', 'required':True, 'domain':[('type','=','cash')]}, | ||
464 | 48 | 'period_id': {'string': 'Period', 'type': 'many2one', 'relation':'account.period', 'required':True}, | ||
465 | 49 | } | ||
466 | 50 | |||
467 | 51 | def _pay_and_reconcile(self, cr, uid, data, context): | ||
468 | 52 | form = data['form'] | ||
469 | 53 | period_id = form.get('period_id', False) | ||
470 | 54 | journal_id = form.get('journal_id', False) | ||
471 | 55 | writeoff_account_id = form.get('writeoff_acc_id', False) | ||
472 | 56 | writeoff_journal_id = form.get('writeoff_journal_id', False) | ||
473 | 57 | pool = pooler.get_pool(cr.dbname) | ||
474 | 58 | cur_obj = pool.get('res.currency') | ||
475 | 59 | amount = form['amount'] | ||
476 | 60 | context['analytic_id'] = form.get('analytic_id', False) | ||
477 | 61 | |||
478 | 62 | invoice = pool.get('account.invoice').browse(cr, uid, data['id'], context) | ||
479 | 63 | journal = pool.get('account.journal').browse(cr, uid, data['form']['journal_id'], context) | ||
480 | 64 | # Compute the amount in company's currency, with the journal currency (which is equal to payment currency) | ||
481 | 65 | # when it is needed : If payment currency (according to selected journal.currency) is <> from company currency | ||
482 | 66 | if journal.currency and invoice.company_id.currency_id.id<>journal.currency.id: | ||
483 | 67 | ctx = {'date':data['form']['date']} | ||
484 | 68 | amount = cur_obj.compute(cr, uid, journal.currency.id, invoice.company_id.currency_id.id, amount, context=ctx) | ||
485 | 69 | currency_id = journal.currency.id | ||
486 | 70 | # Put the paid amount in currency, and the currency, in the context if currency is different from company's currency | ||
487 | 71 | context.update({'amount_currency':form['amount'],'currency_id':currency_id}) | ||
488 | 72 | |||
489 | 73 | if invoice.company_id.currency_id.id<>invoice.currency_id.id: | ||
490 | 74 | ctx = {'date':data['form']['date']} | ||
491 | 75 | amount = cur_obj.compute(cr, uid, invoice.currency_id.id, invoice.company_id.currency_id.id, amount, context=ctx) | ||
492 | 76 | currency_id = invoice.currency_id.id | ||
493 | 77 | # Put the paid amount in currency, and the currency, in the context if currency is different from company's currency | ||
494 | 78 | context.update({'amount_currency':form['amount'],'currency_id':currency_id}) | ||
495 | 79 | |||
496 | 80 | # Take the choosen date | ||
497 | 81 | if form.has_key('comment'): | ||
498 | 82 | context.update({'date_p':form['date'],'comment':form['comment']}) | ||
499 | 83 | else: | ||
500 | 84 | context.update({'date_p':form['date'],'comment':False}) | ||
501 | 85 | |||
502 | 86 | context.update({'account_id':form['account_id'],'cash_amount':form['cash_amount'],'amount_currency':form['amount']}) | ||
503 | 87 | |||
504 | 88 | acc_id = journal.default_credit_account_id and journal.default_credit_account_id.id | ||
505 | 89 | if not acc_id: | ||
506 | 90 | raise wizard.except_wizard(_('Error !'), _('Your journal must have a default credit and debit account.')) | ||
507 | 91 | pool.get('account.invoice').pay_and_reconcile(cr, uid, [data['id']], | ||
508 | 92 | amount, acc_id, period_id, journal_id, writeoff_account_id, | ||
509 | 93 | period_id, writeoff_journal_id, context, data['form']['name']) | ||
510 | 94 | return {} | ||
511 | 95 | |||
512 | 96 | def _wo_check(self, cr, uid, data, context): | ||
513 | 97 | pool = pooler.get_pool(cr.dbname) | ||
514 | 98 | invoice = pool.get('account.invoice').browse(cr, uid, data['id'], context) | ||
515 | 99 | journal = pool.get('account.journal').browse(cr, uid, data['form']['journal_id'], context) | ||
516 | 100 | cur_obj = pool.get('res.currency') | ||
517 | 101 | # Here we need that: | ||
518 | 102 | # The invoice total amount in company's currency <> paid amount in company currency | ||
519 | 103 | # (according to the correct day rate, invoicing rate and payment rate are may be different) | ||
520 | 104 | # => Ask to a write-off of the difference. This could happen even if both amount are equal, | ||
521 | 105 | # because if the currency rate | ||
522 | 106 | # Get the amount in company currency for the invoice (according to move lines) | ||
523 | 107 | inv_amount_company_currency = 0 | ||
524 | 108 | for aml in invoice.move_id.line_id: | ||
525 | 109 | if aml.account_id.id == invoice.account_id.id or aml.account_id.type in ('receivable', 'payable'): | ||
526 | 110 | inv_amount_company_currency += aml.debit | ||
527 | 111 | inv_amount_company_currency -= aml.credit | ||
528 | 112 | inv_amount_company_currency = abs(inv_amount_company_currency) | ||
529 | 113 | |||
530 | 114 | # Get the current amount paid in company currency | ||
531 | 115 | if journal.currency and invoice.company_id.currency_id.id<>journal.currency.id: | ||
532 | 116 | ctx = {'date':data['form']['date']} | ||
533 | 117 | amount_paid = cur_obj.compute(cr, uid, journal.currency.id, invoice.company_id.currency_id.id, data['form']['amount'], round=True, context=ctx) | ||
534 | 118 | else: | ||
535 | 119 | amount_paid = data['form']['amount'] | ||
536 | 120 | # Get the old payment if there are some | ||
537 | 121 | if invoice.payment_ids: | ||
538 | 122 | debit=credit=0.0 | ||
539 | 123 | for payment in invoice.payment_ids: | ||
540 | 124 | debit+=payment.debit | ||
541 | 125 | credit+=payment.credit | ||
542 | 126 | amount_paid+=abs(debit-credit) | ||
543 | 127 | |||
544 | 128 | # Test if there is a difference according to currency rouding setting | ||
545 | 129 | if pool.get('res.currency').is_zero(cr, uid, invoice.company_id.currency_id, | ||
546 | 130 | (amount_paid - inv_amount_company_currency)): | ||
547 | 131 | return 'reconcile' | ||
548 | 132 | return 'addendum' | ||
549 | 133 | |||
550 | 134 | _transaction_add_form = '''<?xml version="1.0"?> | ||
551 | 135 | <form string="Information addendum"> | ||
552 | 136 | <separator string="Write-Off Move" colspan="4"/> | ||
553 | 137 | <field name="writeoff_journal_id"/> | ||
554 | 138 | <field name="writeoff_acc_id" domain="[('type','<>','view'),('type','<>','consolidation')]"/> | ||
555 | 139 | <field name="comment"/> | ||
556 | 140 | <separator string="Analytic" colspan="4"/> | ||
557 | 141 | <field name="analytic_id"/> | ||
558 | 142 | </form>''' | ||
559 | 143 | |||
560 | 144 | _transaction_add_fields = { | ||
561 | 145 | 'writeoff_acc_id': {'string':'Write-Off account', 'type':'many2one', 'relation':'account.account', 'required':True}, | ||
562 | 146 | 'writeoff_journal_id': {'string': 'Write-Off journal', 'type': 'many2one', 'relation':'account.journal', 'required':True}, | ||
563 | 147 | 'comment': {'string': 'Comment', 'type':'char', 'size': 64 , 'required':True}, | ||
564 | 148 | 'analytic_id': {'string':'Analytic Account', 'type': 'many2one', 'relation':'account.analytic.account'}, | ||
565 | 149 | } | ||
566 | 150 | |||
567 | 151 | def _get_value_addendum(self, cr, uid, data, context={}): | ||
568 | 152 | return {'comment': _('Write-Off')} | ||
569 | 153 | |||
570 | 154 | def _compute(self, cr, uid, data, context={}): | ||
571 | 155 | pool = pooler.get_pool(cr.dbname) | ||
572 | 156 | invoice = pool.get('account.invoice').browse(cr, uid, data['id'], context) | ||
573 | 157 | |||
574 | 158 | |||
575 | 159 | def _get_period(self, cr, uid, data, context={}): | ||
576 | 160 | pool = pooler.get_pool(cr.dbname) | ||
577 | 161 | ids = pool.get('account.period').find(cr, uid, context=context) | ||
578 | 162 | period_id = False | ||
579 | 163 | if len(ids): | ||
580 | 164 | period_id = ids[0] | ||
581 | 165 | invoice = pool.get('account.invoice').browse(cr, uid, data['id'], context) | ||
582 | 166 | cash_amount = pool.get('account.invoice')._get_payment(cr, uid, [data['id']], invoice.residual, invoice.payment_term.id, context=context) | ||
583 | 167 | if invoice.state in ['draft', 'proforma2', 'cancel']: | ||
584 | 168 | raise wizard.except_wizard(_('Error !'), _('Can not pay draft/proforma/cancel invoice.')) | ||
585 | 169 | return { | ||
586 | 170 | 'period_id': period_id, | ||
587 | 171 | 'amount': invoice.residual, | ||
588 | 172 | 'date': time.strftime('%Y-%m-%d'), | ||
589 | 173 | 'cash_amount': cash_amount, | ||
590 | 174 | } | ||
591 | 175 | |||
592 | 176 | class wizard_pay_invoice(wizard.interface): | ||
593 | 177 | states = { | ||
594 | 178 | 'init': { | ||
595 | 179 | 'actions': [_get_period], | ||
596 | 180 | 'result': {'type':'form', 'arch':pay_form, 'fields':pay_fields, 'state':[('end','Cancel'),('reconcile','Partial Payment'),('writeoff_check','Full Payment')]} | ||
597 | 181 | }, | ||
598 | 182 | 'writeoff_check': { | ||
599 | 183 | 'actions': [], | ||
600 | 184 | 'result' : {'type': 'choice', 'next_state': _wo_check } | ||
601 | 185 | }, | ||
602 | 186 | 'addendum': { | ||
603 | 187 | 'actions': [_get_value_addendum], | ||
604 | 188 | 'result': {'type': 'form', 'arch':_transaction_add_form, 'fields':_transaction_add_fields, 'state':[('end','Cancel'),('reconcile','Pay and reconcile')]} | ||
605 | 189 | }, | ||
606 | 190 | 'reconcile': { | ||
607 | 191 | 'actions': [_pay_and_reconcile], | ||
608 | 192 | 'result': {'type':'state', 'state':'end'} | ||
609 | 193 | }, | ||
610 | 194 | 'compute_dis': { | ||
611 | 195 | 'actions': [_compute], | ||
612 | 196 | 'result': {'type':'state', 'state':'end'} | ||
613 | 197 | } | ||
614 | 198 | } | ||
615 | 199 | wizard_pay_invoice('account.invoice.pay1') | ||
616 | 200 | |||
617 | 201 | |||
618 | 202 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
619 | 203 |