Merge lp:~npg-team/openobject-addons/account_cash_discount_us_npg into lp:openobject-addons
- account_cash_discount_us_npg
- Merge into trunk
Proposed by
Novapoint Group
Status: | Rejected |
---|---|
Rejected by: | Fabien (Open ERP) |
Proposed branch: | lp:~npg-team/openobject-addons/account_cash_discount_us_npg |
Merge into: | lp:openobject-addons |
Diff against target: |
3188 lines (+3073/-0) 21 files modified
account_cash_discount_us/Change Log.txt (+53/-0) account_cash_discount_us/__init__.py (+26/-0) account_cash_discount_us/__openerp__.py (+54/-0) account_cash_discount_us/__terp__.py (+52/-0) account_cash_discount_us/account_cash_discount.py (+941/-0) account_cash_discount_us/account_cash_discount_us/Change Log.txt (+31/-0) account_cash_discount_us/account_cash_discount_us/__init__.py (+26/-0) account_cash_discount_us/account_cash_discount_us/__openerp__.py (+54/-0) account_cash_discount_us/account_cash_discount_us/__terp__.py (+52/-0) account_cash_discount_us/account_cash_discount_us/account_cash_discount.py (+730/-0) account_cash_discount_us/account_cash_discount_us/account_cash_discount_view.xml (+256/-0) account_cash_discount_us/account_cash_discount_us/i18n/account_cash_discount.pot (+85/-0) account_cash_discount_us/account_cash_discount_us/i18n/fr_BE.po (+85/-0) account_cash_discount_us/account_cash_discount_us/product_view.xml (+19/-0) account_cash_discount_us/account_cash_discount_us/security/ir.model.access.csv (+7/-0) account_cash_discount_us/account_cash_discount_view.xml (+329/-0) account_cash_discount_us/amount_to_words.py (+77/-0) account_cash_discount_us/i18n/account_cash_discount.pot (+85/-0) account_cash_discount_us/i18n/fr_BE.po (+85/-0) account_cash_discount_us/product_view.xml (+19/-0) account_cash_discount_us/security/ir.model.access.csv (+7/-0) |
To merge this branch: | bzr merge lp:~npg-team/openobject-addons/account_cash_discount_us_npg |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
OpenERP Core Team | Pending | ||
Review via email: mp+78430@code.launchpad.net |
Commit message
Description of the change
NovaPoint Group has developed this module to provide the ability to process cash discounts paid on invoices. This works in conjunction with account_
To post a comment you must log in.
Unmerged revisions
- 5304. By Novapoint Group
-
[Add]: account_
cash_discount_ us module to provide cash discounts on invoices
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory 'account_cash_discount_us' | |||
2 | === added file 'account_cash_discount_us/Change Log.txt' | |||
3 | --- account_cash_discount_us/Change Log.txt 1970-01-01 00:00:00 +0000 | |||
4 | +++ account_cash_discount_us/Change Log.txt 2011-10-06 15:23:28 +0000 | |||
5 | @@ -0,0 +1,53 @@ | |||
6 | 1 | =============================================================================== | ||
7 | 2 | Version Change Log (account_cash_discount_us) | ||
8 | 3 | =============================================================================== | ||
9 | 4 | 1.15 (2011-09-16) -> Janeesh | ||
10 | 5 | * Added the onchange on amount in Pay Invoice | ||
11 | 6 | |||
12 | 7 | 1.14 (2011-09-16) -> Arif | ||
13 | 8 | * Removed the onchange on amount in Pay Invoice | ||
14 | 9 | |||
15 | 10 | 1.13 (2011-09-15) -> Sinoj & Arif | ||
16 | 11 | * Fixed the bug on calculation of discount on Pay Invoice | ||
17 | 12 | |||
18 | 13 | 1.12 (2011-07-18) By Arif | ||
19 | 14 | * Added discount field in (Task ID: 362) in supplier payment | ||
20 | 15 | |||
21 | 16 | 1.10 -> 1.11 (2011-04-14) By Jabir | ||
22 | 17 | * Update the payment amount when discount is selected and clicked on recalculate button | ||
23 | 18 | |||
24 | 19 | |||
25 | 20 | 1.08 -> 1.09 (2011-04-14) By Jabir | ||
26 | 21 | * Add calculate button on Supplier Payment | ||
27 | 22 | |||
28 | 23 | 1.08 -> 1.09 (2011-04-08) By Jabir | ||
29 | 24 | * Supplier discount | ||
30 | 25 | |||
31 | 26 | 1.07 -> 1.08 (2011-02-04) By Sinoj | ||
32 | 27 | * Optimization and cleanup | ||
33 | 28 | |||
34 | 29 | |||
35 | 30 | 1.06 -> 1.07 (2010-12-06) By jabir | ||
36 | 31 | * Removed discount wizard and changed domain filtering | ||
37 | 32 | |||
38 | 33 | 1.05 -> 1.06 (2010-12-06) By jabir | ||
39 | 34 | * Take invoice partner instead of moveline partner | ||
40 | 35 | |||
41 | 36 | 1.04 -> 1.05 (2010-11-29) By Jabir | ||
42 | 37 | * Fix placement of Cash Discount Separation Line | ||
43 | 38 | |||
44 | 39 | 1.03 -> 1.04 (2010-11-29) By Sinoj | ||
45 | 40 | * Account posting updated for National account | ||
46 | 41 | |||
47 | 42 | 1.02 -> 1.03 (2010-11-09) By Sinoj | ||
48 | 43 | * "Debit and Credits" wizard button moved to voucher line | ||
49 | 44 | * fields on wizard form are readonly | ||
50 | 45 | * fields on wizard are populated with default values | ||
51 | 46 | * removed | ||
52 | 47 | |||
53 | 48 | 1.01 -> 1.02 (2010-11-04) By jabir | ||
54 | 49 | * Add wizard Discount and Credits | ||
55 | 50 | * Create button Discount and Credits in customer payment form | ||
56 | 51 | |||
57 | 52 | 1.0 -> 1.01 (2010-11-04) By sinoj | ||
58 | 53 | * dependency changed from account_voucher_jdc to account_voucher_credits_us | ||
59 | 0 | \ No newline at end of file | 54 | \ No newline at end of file |
60 | 1 | 55 | ||
61 | === added file 'account_cash_discount_us/__init__.py' | |||
62 | --- account_cash_discount_us/__init__.py 1970-01-01 00:00:00 +0000 | |||
63 | +++ account_cash_discount_us/__init__.py 2011-10-06 15:23:28 +0000 | |||
64 | @@ -0,0 +1,26 @@ | |||
65 | 1 | # -*- coding: utf-8 -*- | ||
66 | 2 | ############################################################################## | ||
67 | 3 | # | ||
68 | 4 | # OpenERP, Open Source Management Solution | ||
69 | 5 | # Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>) | ||
70 | 6 | # Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>) | ||
71 | 7 | # | ||
72 | 8 | # This program is free software: you can redistribute it and/or modify | ||
73 | 9 | # it under the terms of the GNU General Public License as published by | ||
74 | 10 | # the Free Software Foundation, either version 3 of the License, or | ||
75 | 11 | # (at your option) any later version. | ||
76 | 12 | # | ||
77 | 13 | # This program is distributed in the hope that it will be useful, | ||
78 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
79 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
80 | 16 | # GNU General Public License for more details. | ||
81 | 17 | # | ||
82 | 18 | # You should have received a copy of the GNU General Public License | ||
83 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/> | ||
84 | 20 | # | ||
85 | 21 | ############################################################################## | ||
86 | 22 | |||
87 | 23 | |||
88 | 24 | import account_cash_discount | ||
89 | 25 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
90 | 26 | |||
91 | 0 | 27 | ||
92 | === added file 'account_cash_discount_us/__openerp__.py' | |||
93 | --- account_cash_discount_us/__openerp__.py 1970-01-01 00:00:00 +0000 | |||
94 | +++ account_cash_discount_us/__openerp__.py 2011-10-06 15:23:28 +0000 | |||
95 | @@ -0,0 +1,54 @@ | |||
96 | 1 | # -*- coding: utf-8 -*- | ||
97 | 2 | ############################################################################## | ||
98 | 3 | # | ||
99 | 4 | # OpenERP, Open Source Management Solution | ||
100 | 5 | # Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>) | ||
101 | 6 | # Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>) | ||
102 | 7 | # | ||
103 | 8 | # This program is free software: you can redistribute it and/or modify | ||
104 | 9 | # it under the terms of the GNU General Public License as published by | ||
105 | 10 | # the Free Software Foundation, either version 3 of the License, or | ||
106 | 11 | # (at your option) any later version. | ||
107 | 12 | # | ||
108 | 13 | # This program is distributed in the hope that it will be useful, | ||
109 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
110 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
111 | 16 | # GNU General Public License for more details. | ||
112 | 17 | # | ||
113 | 18 | # You should have received a copy of the GNU General Public License | ||
114 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/> | ||
115 | 20 | # | ||
116 | 21 | ############################################################################## | ||
117 | 22 | |||
118 | 23 | |||
119 | 24 | { | ||
120 | 25 | "name" : "Payment Term with Cash Discount", | ||
121 | 26 | "version" : "1.15", | ||
122 | 27 | "depends" : ["account","account_voucher_credits_us","account_cash_discount"], | ||
123 | 28 | "author" : "NovaPoint Group LLC", | ||
124 | 29 | "description" : "Cash discounts, based on payment terms", | ||
125 | 30 | "website" : "http://www.novapointgroup.com/", | ||
126 | 31 | "category" : "Generic Modules/Accounting", | ||
127 | 32 | "description": """ | ||
128 | 33 | This module adds cash discounts on payment terms. Cash discounts | ||
129 | 34 | for a payment term can be configured with: | ||
130 | 35 | * A number of days, | ||
131 | 36 | * A discount (%), | ||
132 | 37 | * A debit and a credit account | ||
133 | 38 | * Sales and Purchase discounts are added to product and invoice line | ||
134 | 39 | """, | ||
135 | 40 | "init_xml" : [ | ||
136 | 41 | ], | ||
137 | 42 | "demo_xml" : [ | ||
138 | 43 | ], | ||
139 | 44 | "update_xml" : [ | ||
140 | 45 | "account_cash_discount_view.xml", | ||
141 | 46 | "product_view.xml", | ||
142 | 47 | "security/ir.model.access.csv", | ||
143 | 48 | ], | ||
144 | 49 | "active": False, | ||
145 | 50 | "installable": True, | ||
146 | 51 | |||
147 | 52 | } | ||
148 | 53 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
149 | 54 | |||
150 | 0 | 55 | ||
151 | === added file 'account_cash_discount_us/__terp__.py' | |||
152 | --- account_cash_discount_us/__terp__.py 1970-01-01 00:00:00 +0000 | |||
153 | +++ account_cash_discount_us/__terp__.py 2011-10-06 15:23:28 +0000 | |||
154 | @@ -0,0 +1,52 @@ | |||
155 | 1 | # -*- encoding: utf-8 -*- | ||
156 | 2 | ############################################################################## | ||
157 | 3 | # | ||
158 | 4 | # OpenERP, Open Source Management Solution | ||
159 | 5 | # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). | ||
160 | 6 | # | ||
161 | 7 | # This program is free software: you can redistribute it and/or modify | ||
162 | 8 | # it under the terms of the GNU Affero General Public License as | ||
163 | 9 | # published by the Free Software Foundation, either version 3 of the | ||
164 | 10 | # License, or (at your option) any later version. | ||
165 | 11 | # | ||
166 | 12 | # This program is distributed in the hope that it will be useful, | ||
167 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
168 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
169 | 15 | # GNU Affero General Public License for more details. | ||
170 | 16 | # | ||
171 | 17 | # You should have received a copy of the GNU Affero General Public License | ||
172 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
173 | 19 | # | ||
174 | 20 | ############################################################################## | ||
175 | 21 | |||
176 | 22 | { | ||
177 | 23 | "name" : "Payment Term with Cash Discount", | ||
178 | 24 | "version" : "1.07", | ||
179 | 25 | "depends" : ["account","account_voucher_credits_us","account_cash_discount"], | ||
180 | 26 | "author" : "Tiny and NovaPoint Group LLC", | ||
181 | 27 | "description" : "Cash discounts, based on payment terms", | ||
182 | 28 | "website" : "http://www.novapointgroup.com/", | ||
183 | 29 | "category" : "Generic Modules/Accounting", | ||
184 | 30 | "description": """ | ||
185 | 31 | This module adds cash discounts on payment terms. Cash discounts | ||
186 | 32 | for a payment term can be configured with: | ||
187 | 33 | * A number of days, | ||
188 | 34 | * A discount (%), | ||
189 | 35 | * A debit and a credit account | ||
190 | 36 | * Sales and Purchase discounts are added to product and invoice line | ||
191 | 37 | """, | ||
192 | 38 | "init_xml" : [ | ||
193 | 39 | ], | ||
194 | 40 | "demo_xml" : [ | ||
195 | 41 | ], | ||
196 | 42 | "update_xml" : [ | ||
197 | 43 | "account_cash_discount_view.xml", | ||
198 | 44 | "product_view.xml", | ||
199 | 45 | "security/ir.model.access.csv", | ||
200 | 46 | ], | ||
201 | 47 | "active": False, | ||
202 | 48 | "installable": True, | ||
203 | 49 | |||
204 | 50 | } | ||
205 | 51 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
206 | 52 | |||
207 | 0 | 53 | ||
208 | === added file 'account_cash_discount_us/account_cash_discount.py' | |||
209 | --- account_cash_discount_us/account_cash_discount.py 1970-01-01 00:00:00 +0000 | |||
210 | +++ account_cash_discount_us/account_cash_discount.py 2011-10-06 15:23:28 +0000 | |||
211 | @@ -0,0 +1,941 @@ | |||
212 | 1 | # -*- coding: utf-8 -*- | ||
213 | 2 | ############################################################################## | ||
214 | 3 | # | ||
215 | 4 | # OpenERP, Open Source Management Solution | ||
216 | 5 | # Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>) | ||
217 | 6 | # Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>) | ||
218 | 7 | # | ||
219 | 8 | # This program is free software: you can redistribute it and/or modify | ||
220 | 9 | # it under the terms of the GNU General Public License as published by | ||
221 | 10 | # the Free Software Foundation, either version 3 of the License, or | ||
222 | 11 | # (at your option) any later version. | ||
223 | 12 | # | ||
224 | 13 | # This program is distributed in the hope that it will be useful, | ||
225 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
226 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
227 | 16 | # GNU General Public License for more details. | ||
228 | 17 | # | ||
229 | 18 | # You should have received a copy of the GNU General Public License | ||
230 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/> | ||
231 | 20 | # | ||
232 | 21 | ############################################################################## | ||
233 | 22 | |||
234 | 23 | from collections import defaultdict | ||
235 | 24 | from mx.DateTime import RelativeDateTime | ||
236 | 25 | from osv import fields, osv | ||
237 | 26 | from tools.translate import _ | ||
238 | 27 | import decimal_precision as dp | ||
239 | 28 | import mx.DateTime | ||
240 | 29 | from amount_to_words import amount_to_words | ||
241 | 30 | from tools.amount_to_text_en import amount_to_text | ||
242 | 31 | |||
243 | 32 | def _combinations(iterable, r): | ||
244 | 33 | ''' | ||
245 | 34 | @return: combination generator object | ||
246 | 35 | |||
247 | 36 | Example | ||
248 | 37 | combinations(’ABCD’, 2) --> AB AC AD BC BD CD | ||
249 | 38 | combinations(range(4), 3) --> 012 013 023 123 | ||
250 | 39 | ''' | ||
251 | 40 | pool = tuple(iterable) | ||
252 | 41 | n = len(pool) | ||
253 | 42 | if r > n: | ||
254 | 43 | return | ||
255 | 44 | indices = range(r) | ||
256 | 45 | yield tuple(pool[i] for i in indices) | ||
257 | 46 | while True: | ||
258 | 47 | for i in reversed(range(r)): | ||
259 | 48 | if indices[i] != i + n - r: | ||
260 | 49 | break | ||
261 | 50 | else: | ||
262 | 51 | return | ||
263 | 52 | indices[i] += 1 | ||
264 | 53 | for j in range(i+1, r): | ||
265 | 54 | indices[j] = indices[j-1] + 1 | ||
266 | 55 | yield tuple(pool[i] for i in indices) | ||
267 | 56 | |||
268 | 57 | |||
269 | 58 | class account_payment_term(osv.osv): | ||
270 | 59 | _name = "account.payment.term" | ||
271 | 60 | _inherit = "account.payment.term" | ||
272 | 61 | _columns = { | ||
273 | 62 | 'cash_discount_ids': fields.one2many('account.cash.discount', 'payment_id', 'Cash Discounts'), | ||
274 | 63 | } | ||
275 | 64 | def get_discounts(self, cr, uid, id, base_date, context={}): | ||
276 | 65 | """ | ||
277 | 66 | return the list of (date,percentage) ordered by date for the | ||
278 | 67 | payment term with the corresponding id. return [] if no cash | ||
279 | 68 | discount are defined. base_date is the date from where the | ||
280 | 69 | discounts are computed. | ||
281 | 70 | """ | ||
282 | 71 | res=[] | ||
283 | 72 | for pt in self.browse(cr, uid, id, context): | ||
284 | 73 | |||
285 | 74 | if not pt.cash_discount_ids: | ||
286 | 75 | continue | ||
287 | 76 | |||
288 | 77 | for d in pt.cash_discount_ids: | ||
289 | 78 | res.append( | ||
290 | 79 | ((mx.DateTime.strptime(base_date,'%Y-%m-%d') +\ | ||
291 | 80 | RelativeDateTime(days=d.delay)).strftime("%Y-%m-%d"), | ||
292 | 81 | d.discount) | ||
293 | 82 | ) | ||
294 | 83 | |||
295 | 84 | res.sort(cmp=lambda x,y: cmp(x[0],y[0])) | ||
296 | 85 | return res | ||
297 | 86 | account_payment_term() | ||
298 | 87 | |||
299 | 88 | class account_invoice(osv.osv): | ||
300 | 89 | ''' | ||
301 | 90 | Add discount calculation to invoice | ||
302 | 91 | ''' | ||
303 | 92 | _inherit = 'account.invoice' | ||
304 | 93 | |||
305 | 94 | def _get_discount(self, cr, uid, ids, field_name, args, context={}): | ||
306 | 95 | ''' | ||
307 | 96 | Calculate the value of variable date_discount (Discount Date) and amount_discounted (Discounted Total) | ||
308 | 97 | ''' | ||
309 | 98 | |||
310 | 99 | if context is None: | ||
311 | 100 | context = {} | ||
312 | 101 | for invoice in self.browse(cr, uid, ids, context): | ||
313 | 102 | res = defaultdict(list) | ||
314 | 103 | res[invoice.id] = { | ||
315 | 104 | 'date_discount': invoice.date_due, | ||
316 | 105 | 'amount_discounted': invoice.amount_total | ||
317 | 106 | } | ||
318 | 107 | if not invoice.date_invoice: | ||
319 | 108 | invoice_date = mx.DateTime.today().strftime("%Y-%m-%d") | ||
320 | 109 | self.write(cr, uid, [invoice.id], {'date_invoice': invoice_date}, context) | ||
321 | 110 | else: | ||
322 | 111 | invoice_date = invoice.date_invoice | ||
323 | 112 | discounts = invoice.payment_term and invoice.payment_term.get_discounts(invoice_date, context=context) | ||
324 | 113 | if discounts: | ||
325 | 114 | line_obj = self.pool.get('account.invoice.line') | ||
326 | 115 | discount_total = 0.0 | ||
327 | 116 | non_discount_total = 0.0 | ||
328 | 117 | for line in invoice.invoice_line: | ||
329 | 118 | if line.cash_discount: | ||
330 | 119 | discount_total += line.price_subtotal | ||
331 | 120 | line_cash_discount = round((1.0 - discounts[0][1]) * line.price_subtotal) | ||
332 | 121 | line_obj.write(cr, uid, line.id, {'cash_discount': line_cash_discount}, context) | ||
333 | 122 | else: | ||
334 | 123 | non_discount_total += line.price_subtotal | ||
335 | 124 | line_obj.write(cr, uid, line.id, {'cash_discount': 0.0}, context) | ||
336 | 125 | # assume taxes are never discountable | ||
337 | 126 | non_discount_total += invoice.amount_tax | ||
338 | 127 | # There may be more than one - return the earliest | ||
339 | 128 | res[invoice.id] = { | ||
340 | 129 | 'date_discount': discounts[0][0], | ||
341 | 130 | 'amount_discounted': round(((1.0 - discounts[0][1]) * discount_total) + non_discount_total,2) | ||
342 | 131 | } | ||
343 | 132 | return defaultdict(type([]),res) | ||
344 | 133 | |||
345 | 134 | _columns = { | ||
346 | 135 | 'date_discount': fields.function(_get_discount, method=True, type='date', string='Discount Date', multi='all'), | ||
347 | 136 | 'amount_discounted': fields.function(_get_discount, method=True, type='float', digits_compute=dp.get_precision('Account'), string='Discounted Total', | ||
348 | 137 | multi='all'), | ||
349 | 138 | } | ||
350 | 139 | account_invoice() | ||
351 | 140 | |||
352 | 141 | class account_invoice_pay_writeoff(osv.osv_memory): | ||
353 | 142 | """ | ||
354 | 143 | Opens the write off amount pay form. | ||
355 | 144 | """ | ||
356 | 145 | _name = "account.invoice.pay.writeoff" | ||
357 | 146 | _description = "Pay Invoice " | ||
358 | 147 | _columns = { | ||
359 | 148 | 'writeoff_acc_id': fields.many2one('account.account', 'Write-Off account', required=True), | ||
360 | 149 | 'writeoff_journal_id': fields.many2one('account.journal', 'Write-Off journal', required=True), | ||
361 | 150 | 'comment': fields.char('Comment', size=64, required=True), | ||
362 | 151 | 'analytic_id': fields.many2one('account.analytic.account','Analytic Account'), | ||
363 | 152 | } | ||
364 | 153 | _defaults = { | ||
365 | 154 | 'comment': 'Write-Off', | ||
366 | 155 | } | ||
367 | 156 | |||
368 | 157 | account_invoice_pay_writeoff() | ||
369 | 158 | |||
370 | 159 | class account_invoice_pay(osv.osv_memory): | ||
371 | 160 | """ | ||
372 | 161 | Generate pay invoice wizard, user can make partial or full payment for invoice. | ||
373 | 162 | """ | ||
374 | 163 | _name = "account.invoice.pay" | ||
375 | 164 | _description = "Pay Invoice " | ||
376 | 165 | _columns = { | ||
377 | 166 | 'amount': fields.float('Amount paid', required=True, digits_compute = dp.get_precision('Account')), | ||
378 | 167 | 'name': fields.char('Entry Name', size=64, required=True), | ||
379 | 168 | 'date': fields.date('Date payment', required=True), | ||
380 | 169 | 'journal_id': fields.many2one('account.journal', 'Journal/Payment Mode', required=True, domain=[('type','=','cash')]), | ||
381 | 170 | 'period_id': fields.many2one('account.period', 'Period', required=True), | ||
382 | 171 | } | ||
383 | 172 | |||
384 | 173 | def view_init(self, cr, uid, ids, context=None): | ||
385 | 174 | invoice = self.pool.get('account.invoice').browse(cr, uid, context['active_id'], context=context) | ||
386 | 175 | if invoice.state in ['draft', 'proforma2', 'cancel']: | ||
387 | 176 | raise osv.except_osv(_('Error !'), _('Can not pay draft/proforma/cancel invoice.')) | ||
388 | 177 | pass | ||
389 | 178 | |||
390 | 179 | def _get_period(self, cr, uid, context=None): | ||
391 | 180 | ''' | ||
392 | 181 | Initialise Period | ||
393 | 182 | ''' | ||
394 | 183 | ids = self.pool.get('account.period').find(cr, uid, context=context) | ||
395 | 184 | period_id = False | ||
396 | 185 | if len(ids): | ||
397 | 186 | period_id = ids[0] | ||
398 | 187 | return period_id | ||
399 | 188 | |||
400 | 189 | def _get_amount(self, cr, uid, context=None): | ||
401 | 190 | ''' | ||
402 | 191 | Get default value of Amount paid | ||
403 | 192 | ''' | ||
404 | 193 | return self.pool.get('account.invoice').browse(cr, uid, context['active_id'], context=context).residual | ||
405 | 194 | |||
406 | 195 | _defaults = { | ||
407 | 196 | 'date': lambda *a: time.strftime('%Y-%m-%d'), | ||
408 | 197 | 'period_id': _get_period, | ||
409 | 198 | 'amount': _get_amount, | ||
410 | 199 | } | ||
411 | 200 | account_invoice_pay() | ||
412 | 201 | |||
413 | 202 | class account_voucher(osv.osv): | ||
414 | 203 | _name = 'account.voucher' | ||
415 | 204 | _inherit = 'account.voucher' | ||
416 | 205 | def calc_supp_diff(self, cr, uid, ids, context={}): | ||
417 | 206 | ''' | ||
418 | 207 | Called by calculate/re-calculate action. | ||
419 | 208 | This method will update the credit lines on voucher lines. | ||
420 | 209 | If the field "auto_match" marked, this method will run a matching routine | ||
421 | 210 | ''' | ||
422 | 211 | res = {'nodestroy':True} | ||
423 | 212 | amount_cash_discount = 0.0 | ||
424 | 213 | amount_interest = 0.0 | ||
425 | 214 | |||
426 | 215 | for vch in self.browse(cr, uid, ids): | ||
427 | 216 | for line in vch.line_dr_ids: | ||
428 | 217 | ''' | ||
429 | 218 | Update the credit lines and discount lines so that matching routine can use the latest available credits and discounts | ||
430 | 219 | ''' | ||
431 | 220 | # line._update_debit_lines( context=context) | ||
432 | 221 | line._update_supp_discount_lines(context=context) | ||
433 | 222 | |||
434 | 223 | # if vch.auto_match: | ||
435 | 224 | # ''' | ||
436 | 225 | # Try the matching routine including the manual selection | ||
437 | 226 | # ''' | ||
438 | 227 | # ret = self._find_exact_match(cr, uid, vch.line_cr_ids, vch.amount, mark_pay=False, use_discount=False, context=False) | ||
439 | 228 | # if not ret: | ||
440 | 229 | # ''' | ||
441 | 230 | # Try to match considering all voucher lines | ||
442 | 231 | # ''' | ||
443 | 232 | # ret = self._find_exact_match(cr, uid, vch.line_cr_ids, vch.amount, mark_pay=True, use_discount=False, context=False) | ||
444 | 233 | # if not ret: | ||
445 | 234 | # ''' | ||
446 | 235 | # Try to match considering discount | ||
447 | 236 | # ''' | ||
448 | 237 | # ret = self._find_exact_match(cr, uid, vch.line_cr_ids, vch.amount, mark_pay=True, use_discount=True, context=False) | ||
449 | 238 | |||
450 | 239 | return res | ||
451 | 240 | |||
452 | 241 | def _update_discounts(self, lines, vch_date): | ||
453 | 242 | date_discount = False | ||
454 | 243 | amount_discount = False | ||
455 | 244 | for line in lines: | ||
456 | 245 | if 'date_discount' in line: | ||
457 | 246 | date_discount = line['date_discount'] | ||
458 | 247 | amount_discounted = line['amount_discounted'] | ||
459 | 248 | else: | ||
460 | 249 | return | ||
461 | 250 | if line['amount'] >= line['amount_unreconciled']: | ||
462 | 251 | amount_discount = 0.0 | ||
463 | 252 | elif vch_date <= date_discount and line['amount'] <= line['amount_unreconciled'] and line['amount'] >= amount_discounted: | ||
464 | 253 | amount_discount = max(line['amount_unreconciled'] - amount_discounted, 0.0) | ||
465 | 254 | elif vch_date <= date_discount and line['amount'] < amount_discounted: | ||
466 | 255 | amount_discount = max(line['amount_unreconciled'] - amount_discounted, 0.0) | ||
467 | 256 | line['cash_discount'] = amount_discount | ||
468 | 257 | line['amount_difference'] = line['amount_unreconciled'] - line['amount'] - amount_discount | ||
469 | 258 | |||
470 | 259 | |||
471 | 260 | def onchange_partner_id(self, cr, uid, ids, partner_id, journal_id, price, currency_id, ttype, date, context={}): | ||
472 | 261 | ''' | ||
473 | 262 | Function to update fields in customer payment form on changing customer | ||
474 | 263 | ''' | ||
475 | 264 | if context is None: | ||
476 | 265 | context = {} | ||
477 | 266 | |||
478 | 267 | currency_pool = self.pool.get('res.currency') | ||
479 | 268 | journal_pool = self.pool.get('account.journal') | ||
480 | 269 | invoice_pool = self.pool.get('account.invoice') | ||
481 | 270 | line_pool = self.pool.get('account.voucher.line') | ||
482 | 271 | move_line_pool = self.pool.get('account.move.line') | ||
483 | 272 | partner_pool = self.pool.get('res.partner') | ||
484 | 273 | company_currency = False | ||
485 | 274 | |||
486 | 275 | default = super(account_voucher, self).onchange_partner_id(cr, uid, ids, partner_id, journal_id, price, currency_id, ttype, date, context={}) | ||
487 | 276 | if not partner_id: | ||
488 | 277 | return default | ||
489 | 278 | # we have to clear out lines, because new lines will be created by the change | ||
490 | 279 | if partner_id and not journal_id: | ||
491 | 280 | partner = partner_pool.browse(cr, uid, partner_id, context) | ||
492 | 281 | if partner._columns.has_key('payment_meth_id') and partner.payment_meth_id: | ||
493 | 282 | payment_mode_pool = self.pool.get('payment.mode') | ||
494 | 283 | payment_meth = payment_mode_pool.browse(cr, uid, partner.payment_meth_id.id, context) | ||
495 | 284 | if payment_meth: | ||
496 | 285 | default['value']['journal_id'] = payment_meth.journal.id | ||
497 | 286 | journal_id = payment_meth.journal.id | ||
498 | 287 | if ids: | ||
499 | 288 | line_ids = line_pool.search(cr, uid, [('voucher_id','=',ids[0])]) | ||
500 | 289 | if line_ids: | ||
501 | 290 | line_pool.unlink(cr, uid, line_ids) | ||
502 | 291 | if journal_id: | ||
503 | 292 | journal = journal_pool.browse(cr, uid, journal_id) | ||
504 | 293 | company_currency = journal.company_id.currency_id.id | ||
505 | 294 | |||
506 | 295 | total_credit = 0.0 | ||
507 | 296 | total_debit = 0.0 | ||
508 | 297 | vch_date = False | ||
509 | 298 | for vch in self.browse(cr, uid, ids): | ||
510 | 299 | vch_date = vch.date | ||
511 | 300 | if default and 'value' in default and 'line_cr_ids' in default['value']: | ||
512 | 301 | for line in default['value']['line_cr_ids']: | ||
513 | 302 | invoice_id = invoice_pool.search(cr, uid, [('number', '=', line['name'])]) | ||
514 | 303 | if invoice_id: | ||
515 | 304 | line['invoice_id'] = invoice_id[0] | ||
516 | 305 | invoice = invoice_pool.browse(cr, uid, invoice_id[0], ) | ||
517 | 306 | date_discount = invoice.date_discount | ||
518 | 307 | amount_discounted = invoice.amount_discounted | ||
519 | 308 | line['date_discount'] = date_discount | ||
520 | 309 | line['amount_discounted'] = amount_discounted | ||
521 | 310 | else: | ||
522 | 311 | line['date_discount'] = False | ||
523 | 312 | line['amount_discounted'] = 0.0 | ||
524 | 313 | line['amount'] = 0.0 | ||
525 | 314 | total_credit += line['type'] == 'cr' and line['amount_unreconciled'] or 0.0 | ||
526 | 315 | total_debit += line['type'] == 'dr' and line['amount_unreconciled'] or 0.0 | ||
527 | 316 | # first, see if we can find an invoice matching the amount to be applied | ||
528 | 317 | found = False | ||
529 | 318 | def calc_amount(line, total): | ||
530 | 319 | return min(line['amount_unreconciled'], total) | ||
531 | 320 | lines = default['value']['line_cr_ids'] | ||
532 | 321 | if len(lines) == 0: | ||
533 | 322 | return default | ||
534 | 323 | # return False | ||
535 | 324 | # if only one, assign it | ||
536 | 325 | if len(lines) == 1: | ||
537 | 326 | for line in lines: | ||
538 | 327 | if line['type'] == 'cr': | ||
539 | 328 | amount = price | ||
540 | 329 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, amount) or amount | ||
541 | 330 | total_credit -= amount | ||
542 | 331 | found = True | ||
543 | 332 | break | ||
544 | 333 | else: | ||
545 | 334 | amount = price | ||
546 | 335 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, amount) or amount | ||
547 | 336 | total_debit -= amount | ||
548 | 337 | found = True | ||
549 | 338 | break | ||
550 | 339 | self._update_discounts(lines, vch_date) | ||
551 | 340 | if not found: | ||
552 | 341 | for line in lines: | ||
553 | 342 | if line['amount_unreconciled'] == price: | ||
554 | 343 | if line['type'] == 'cr': | ||
555 | 344 | amount = calc_amount(line, total_credit) | ||
556 | 345 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, amount) or amount | ||
557 | 346 | total_credit -= amount | ||
558 | 347 | found = True | ||
559 | 348 | break | ||
560 | 349 | else: | ||
561 | 350 | amount = calc_amount(line, total_debit) | ||
562 | 351 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, amount) or amount | ||
563 | 352 | total_debit -= amount | ||
564 | 353 | found = True | ||
565 | 354 | break | ||
566 | 355 | if not found: | ||
567 | 356 | # see if we can find a combination that matches | ||
568 | 357 | def search(lines, price): | ||
569 | 358 | for i in range(0, len(lines)): | ||
570 | 359 | if lines[i]['amount_unreconciled'] == price: | ||
571 | 360 | return [lines[i]] | ||
572 | 361 | for i in range(0, len(lines)): | ||
573 | 362 | for j in range(i + 1, len(lines)): | ||
574 | 363 | if lines[i]['amount_unreconciled'] + lines[j]['amount_unreconciled'] == price: | ||
575 | 364 | return [lines[i],lines[j]] | ||
576 | 365 | for i in range(0, len(lines)): | ||
577 | 366 | for j in range(i + 1, len(lines)): | ||
578 | 367 | for k in range(j + 1, len(lines)): | ||
579 | 368 | if lines[i]['amount_unreconciled'] + lines[j]['amount_unreconciled'] + lines[k]['amount_unreconciled']== price: | ||
580 | 369 | return [lines[i],lines[j],lines[k]] | ||
581 | 370 | line_ids = search(lines, price) | ||
582 | 371 | |||
583 | 372 | if line_ids: # and sum == price: | ||
584 | 373 | for line in line_ids: | ||
585 | 374 | if line['type'] == 'cr': | ||
586 | 375 | amount = calc_amount(line, line['amount_unreconciled']) | ||
587 | 376 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, amount) | ||
588 | 377 | total_debit -= amount | ||
589 | 378 | found = True | ||
590 | 379 | else: | ||
591 | 380 | amount = calc_amount(line, line['amount_unreconciled']) | ||
592 | 381 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, amount) | ||
593 | 382 | total_credit -= amount | ||
594 | 383 | found = True | ||
595 | 384 | if not found: | ||
596 | 385 | # see if we can find a match using discounted amount | ||
597 | 386 | def search2(lines, price): | ||
598 | 387 | for i in range(0, len(lines)): | ||
599 | 388 | if min(lines[i]['amount_unreconciled'],lines[i]['amount_discounted']) == price: | ||
600 | 389 | return [lines[i]] | ||
601 | 390 | for i in range(0, len(lines)): | ||
602 | 391 | for j in range(i + 1, len(lines)): | ||
603 | 392 | if min(lines[i]['amount_unreconciled'],lines[i]['amount_discounted']) + min(lines[j]['amount_unreconciled'],lines[j]['amount_discounted']) == price: | ||
604 | 393 | return [lines[i],lines[j]] | ||
605 | 394 | for i in range(0, len(lines)): | ||
606 | 395 | for j in range(i + 1, len(lines)): | ||
607 | 396 | for k in range(j + 1, len(lines)): | ||
608 | 397 | if min(lines[i]['amount_unreconciled'],lines[i]['amount_discounted']) + min(lines[j]['amount_unreconciled'],lines[j]['amount_discounted']) + min(lines[k]['amount_unreconciled'],lines[k]['amount_discounted']) == price: | ||
609 | 398 | return [lines[i],lines[j],lines[k]] | ||
610 | 399 | line_ids = search(lines, price) | ||
611 | 400 | lines = default['value']['line_cr_ids'] | ||
612 | 401 | line_ids = search2(lines, price) | ||
613 | 402 | if line_ids: | ||
614 | 403 | for line in line_ids: | ||
615 | 404 | if line['type'] == 'cr': | ||
616 | 405 | amount = calc_amount(line, min(line['amount_unreconciled'],line['amount_discounted'])) | ||
617 | 406 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, min(line['amount_unreconciled'],line['amount_discounted'])) | ||
618 | 407 | total_debit -= amount | ||
619 | 408 | found = True | ||
620 | 409 | else: | ||
621 | 410 | amount = calc_amount(line, min(line['amount_unreconciled'],line['amount_discounted'])) | ||
622 | 411 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, min(line['amount_unreconciled'],line['amount_discounted'])) | ||
623 | 412 | total_credit -= amount | ||
624 | 413 | found = True | ||
625 | 414 | lines = default['value']['line_cr_ids'] | ||
626 | 415 | ''' | ||
627 | 416 | FIXME : removing amount from line_dr_ids (Credits on customer payment form) line. | ||
628 | 417 | and amount from line_cr_ids (Invoice and outstanding transactions on customer payment form) line | ||
629 | 418 | I do not think this this is a good solution. But it works. | ||
630 | 419 | The whole "onchange_partner_id" function need a re-thinking (may have to rewrite it completely instead of calling super ). | ||
631 | 420 | ''' | ||
632 | 421 | if default: | ||
633 | 422 | for credit_line in default['value'].get('line_dr_ids',[]): | ||
634 | 423 | credit_line['amount'] = 0.0 | ||
635 | 424 | for invoce_line in default['value'].get('line_cr_ids',[]): | ||
636 | 425 | invoce_line['amount'] = 0.0 | ||
637 | 426 | invoce_line['amount_difference'] = invoce_line['amount_unreconciled'] | ||
638 | 427 | return default | ||
639 | 428 | |||
640 | 429 | def calc_cash_discount(self, cr, uid, ids, vch, line, context={}): | ||
641 | 430 | ''' | ||
642 | 431 | Calculate discount per line | ||
643 | 432 | ''' | ||
644 | 433 | total_allocated = 0.0 | ||
645 | 434 | for line in vch.line_ids: | ||
646 | 435 | total_allocated += line.amount | ||
647 | 436 | context.update({'total_allocated': total_allocated, 'total_amount': vch.date}) | ||
648 | 437 | amount_discount = 0.0 | ||
649 | 438 | if line.amount >= line.amount_unreconciled or line.amount < 0.01 : | ||
650 | 439 | amount_discount = 0.0 | ||
651 | 440 | elif line.amount >= line.amount_discounted and vch.date <= line.date_discount: | ||
652 | 441 | amount_discount = line.amount_unreconciled - line.amount_discounted | ||
653 | 442 | return amount_discount | ||
654 | 443 | |||
655 | 444 | |||
656 | 445 | def onchange_amount(self, cr, uid, ids, amount, context={}): | ||
657 | 446 | if not context: | ||
658 | 447 | context = {} | ||
659 | 448 | result = {} | ||
660 | 449 | currency_format = self.pool.get('res.users').browse(cr, uid, uid).company_id.currency_format | ||
661 | 450 | if currency_format=='us': | ||
662 | 451 | amount_in_words = amount_to_words(amount) | ||
663 | 452 | else: amount_in_words = amount_to_text(amount) | ||
664 | 453 | result['amount_in_word']=amount_in_words | ||
665 | 454 | return {'value':result} | ||
666 | 455 | account_voucher() | ||
667 | 456 | |||
668 | 457 | class account_voucher_line(osv.osv): | ||
669 | 458 | _name = 'account.voucher.line' | ||
670 | 459 | _inherit = 'account.voucher.line' | ||
671 | 460 | def onchange_supp_pay(self, cr, uid, ids, line_amount, pay, amount_unreconciled,par_cr_ids, par_amount, credit_used, discount_used, writeoff_amount=0, context={}): | ||
672 | 461 | ''' | ||
673 | 462 | Function to automatically fill the values when the pay checkbox is selected | ||
674 | 463 | ''' | ||
675 | 464 | ret = {} | ||
676 | 465 | writeoff_amount = (not writeoff_amount and [0] or [writeoff_amount])[0] | ||
677 | 466 | discount_used = (not discount_used and [0] or [discount_used])[0] | ||
678 | 467 | credit_used = (not credit_used and [0] or [credit_used])[0] | ||
679 | 468 | if pay: | ||
680 | 469 | tot_amt = par_amount + line_amount | ||
681 | 470 | for credit in par_cr_ids: | ||
682 | 471 | if credit[2].get('pay'): | ||
683 | 472 | tot_amt -= (credit[2]['amount']) | ||
684 | 473 | if tot_amt < 0: | ||
685 | 474 | ret['amount'] = 0.0 | ||
686 | 475 | else: | ||
687 | 476 | amount_unreconciled -= (discount_used+writeoff_amount+credit_used) | ||
688 | 477 | ret['amount'] = min(tot_amt,(amount_unreconciled<0) and 0 or amount_unreconciled) | ||
689 | 478 | else: | ||
690 | 479 | ret['amount'] = 0.0 | ||
691 | 480 | return {'value':ret} | ||
692 | 481 | def recalculate_supp_values(self, cr, uid, ids, context={}): | ||
693 | 482 | ''' | ||
694 | 483 | Re-calculate button action | ||
695 | 484 | ''' | ||
696 | 485 | if type(ids) == type([]): | ||
697 | 486 | voucher_line = self.browse(cr,uid,ids[0]) | ||
698 | 487 | else: | ||
699 | 488 | voucher_line = self.browse(cr,uid,ids) | ||
700 | 489 | if voucher_line.discount_used: | ||
701 | 490 | print "discount_useddiscount_useddiscount_useddiscount_useddiscount_useddiscount_useddiscount_useddiscount_useddiscount_useddiscount_used" | ||
702 | 491 | self.write(cr,uid,ids,{'amount':voucher_line.amount_unreconciled - voucher_line.discount_used}) | ||
703 | 492 | self.pool.get('account.voucher').calc_supp_diff(cr, uid, [voucher_line.voucher_id.id]) | ||
704 | 493 | return True | ||
705 | 494 | |||
706 | 495 | |||
707 | 496 | |||
708 | 497 | def _update_credit_lines(self,cr, uid, ids, context): | ||
709 | 498 | ''' | ||
710 | 499 | Function to update the credit lines in payment lines | ||
711 | 500 | ''' | ||
712 | 501 | credits_used_pool = self.pool.get('account.voucher.line.credits_to_use') | ||
713 | 502 | for line in self.browse(cr , uid, ids, context): | ||
714 | 503 | credits_lines_used = [x.orginal_credit_line_id.id for x in line.available_credits] | ||
715 | 504 | for credit_line in line.voucher_id.line_dr_ids : | ||
716 | 505 | if credit_line.id not in credits_lines_used and line.invoice_id and line.invoice_id.payment_term: | ||
717 | 506 | credits_used_pool.create(cr, uid, { | ||
718 | 507 | 'voucher_line_id': line.id, | ||
719 | 508 | 'orginal_credit_line_id':credit_line.id, | ||
720 | 509 | 'use_credit': False, | ||
721 | 510 | 'inv_credit': credit_line.move_line_id.id, | ||
722 | 511 | 'discount_window_date': credit_line.date_original, | ||
723 | 512 | 'orginal_amount': credit_line.amount_original, | ||
724 | 513 | 'available_amount': credit_line.amount_unreconciled - credit_line.pending_credits, | ||
725 | 514 | 'discount_amount': 0.0, | ||
726 | 515 | 'gl_account' : credit_line.account_id.id,}) | ||
727 | 516 | else : | ||
728 | 517 | to_update_credit_line_ids = credits_used_pool.search(cr,uid,[('voucher_line_id','=',line.id),( 'orginal_credit_line_id','=',credit_line.id)], context=context) | ||
729 | 518 | if to_update_credit_line_ids: | ||
730 | 519 | credits_used_pool.write(cr, uid,to_update_credit_line_ids,{'available_amount': credit_line.amount_unreconciled-credit_line.pending_credits}, context=context) | ||
731 | 520 | |||
732 | 521 | def _update_discount_lines(self,cr, uid, ids, context): | ||
733 | 522 | ''' | ||
734 | 523 | Function to update the discount lines in payment lines | ||
735 | 524 | ''' | ||
736 | 525 | |||
737 | 526 | discount_used_pool = self.pool.get('account.voucher.line.discount_to_use') | ||
738 | 527 | user_pool = self.pool.get('res.users') | ||
739 | 528 | user = user_pool.browse(cr, uid, uid, context) | ||
740 | 529 | for line in self.browse(cr , uid, ids, context): | ||
741 | 530 | if line.invoice_id: | ||
742 | 531 | if not line.invoice_id.date_discount or not line.voucher_id.date or line.voucher_id.date > line.invoice_id.date_discount: | ||
743 | 532 | ''' | ||
744 | 533 | customer is not eligible for the discount | ||
745 | 534 | ''' | ||
746 | 535 | continue | ||
747 | 536 | |||
748 | 537 | discount = line.invoice_id.amount_total - line.invoice_id.amount_discounted | ||
749 | 538 | date_discount = line.invoice_id.date_discount | ||
750 | 539 | discount_found = False | ||
751 | 540 | for discount_line in line.available_discounts: | ||
752 | 541 | #if abs(discount - discount_line.proposed_discount) < 0.01 and line.invoice_id.payment_term.id == discount_line.inv_payment_terms.id: | ||
753 | 542 | if line.invoice_id.payment_term.id == discount_line.inv_payment_terms.id: | ||
754 | 543 | discount_found = True | ||
755 | 544 | continue | ||
756 | 545 | if not discount_found and user.company_id.sales_discount_account: | ||
757 | 546 | ''' | ||
758 | 547 | TODO : calculate/findout the discount_window_date (The last day of the discount window. To receive discounts payments must be paid on or before this date.) | ||
759 | 548 | ''' | ||
760 | 549 | discount_used_pool.create(cr, uid, { | ||
761 | 550 | 'voucher_line_id': line.id, | ||
762 | 551 | 'use_discount': False, | ||
763 | 552 | 'inv_payment_terms':line.invoice_id.payment_term.id , | ||
764 | 553 | 'discount_window_date': date_discount, | ||
765 | 554 | 'proposed_discount': discount, | ||
766 | 555 | 'discount_amount': 0.0, | ||
767 | 556 | 'gl_account':user.company_id.sales_discount_account.id | ||
768 | 557 | }, context=context) | ||
769 | 558 | |||
770 | 559 | def _update_supp_discount_lines(self,cr, uid, ids, context): | ||
771 | 560 | ''' | ||
772 | 561 | Function to update the discount lines in payment lines | ||
773 | 562 | ''' | ||
774 | 563 | |||
775 | 564 | discount_used_pool = self.pool.get('account.voucher.line.discount_to_use') | ||
776 | 565 | user_pool = self.pool.get('res.users') | ||
777 | 566 | user = user_pool.browse(cr, uid, uid, context) | ||
778 | 567 | for line in self.browse(cr , uid, ids, context): | ||
779 | 568 | if line.invoice_id: | ||
780 | 569 | if not line.invoice_id.date_discount or not line.voucher_id.date or line.voucher_id.date > line.invoice_id.date_discount: | ||
781 | 570 | ''' | ||
782 | 571 | customer is not eligible for the discount | ||
783 | 572 | ''' | ||
784 | 573 | continue | ||
785 | 574 | |||
786 | 575 | discount = line.invoice_id.amount_total - line.invoice_id.amount_discounted | ||
787 | 576 | date_discount = line.invoice_id.date_discount | ||
788 | 577 | discount_found = False | ||
789 | 578 | for discount_line in line.available_discounts: | ||
790 | 579 | #if abs(discount - discount_line.proposed_discount) < 0.01 and line.invoice_id.payment_term.id == discount_line.inv_payment_terms.id: | ||
791 | 580 | if line.invoice_id.payment_term.id == discount_line.inv_payment_terms.id: | ||
792 | 581 | discount_found = True | ||
793 | 582 | continue | ||
794 | 583 | if not discount_found and user.company_id.purchase_discount_account: | ||
795 | 584 | ''' | ||
796 | 585 | TODO : calculate/findout the discount_window_date (The last day of the discount window. To receive discounts payments must be paid on or before this date.) | ||
797 | 586 | ''' | ||
798 | 587 | discount_used_pool.create(cr, uid, { | ||
799 | 588 | 'voucher_line_id': line.id, | ||
800 | 589 | 'use_discount': False, | ||
801 | 590 | 'inv_payment_terms':line.invoice_id.payment_term.id , | ||
802 | 591 | 'discount_window_date': date_discount, | ||
803 | 592 | 'proposed_discount': discount, | ||
804 | 593 | 'discount_amount': 0.0, | ||
805 | 594 | 'gl_account':user.company_id.purchase_discount_account.id | ||
806 | 595 | }, context=context) | ||
807 | 596 | |||
808 | 597 | |||
809 | 598 | def _compute_discount_used(self, cr, uid, ids, name, args, context=None): | ||
810 | 599 | ''' | ||
811 | 600 | Function to calculate the value of variable discount used | ||
812 | 601 | ''' | ||
813 | 602 | res = {} | ||
814 | 603 | for line in self.browse(cr, uid, ids): | ||
815 | 604 | res[line.id] = 0.0 | ||
816 | 605 | for discount_line in line.available_discounts: | ||
817 | 606 | if discount_line.use_discount : | ||
818 | 607 | res[line.id] += discount_line.discount_amount | ||
819 | 608 | return res | ||
820 | 609 | |||
821 | 610 | def _compute_balance(self, cr, uid, ids, name, args, context=None): | ||
822 | 611 | ''' | ||
823 | 612 | Function to calculate the value of variables Cash Discount, Interest and Amt Due | ||
824 | 613 | ''' | ||
825 | 614 | currency_pool = self.pool.get('res.currency') | ||
826 | 615 | rs_data = super(account_voucher_line, self)._compute_balance(cr, uid, ids, name, args, context) | ||
827 | 616 | for line in self.browse(cr, uid, ids): | ||
828 | 617 | amount_cash_discount = self.calc_cash_discount(cr, uid, ids, vch, line) | ||
829 | 618 | amount_interest = self.calc_interest(vch, line, line.amount) | ||
830 | 619 | amount_unreconciled = 0.0 | ||
831 | 620 | move_line = line.move_line_id or False | ||
832 | 621 | if move_line: | ||
833 | 622 | amount_unreconciled = currency_pool.compute(cr, uid, company_currency, voucher_currency, move_line.amount_unreconciled - amount_cash_discount - line.writeoff) | ||
834 | 623 | rs_data[line.id] = {'cash_discount': amount_cash_discount, 'interest': amount_interest, 'amount_unreconciled': amount_unreconciled} | ||
835 | 624 | return rs_data | ||
836 | 625 | |||
837 | 626 | def _get_discount(self, cr, uid, ids, field_name, args, context={}): | ||
838 | 627 | """ | ||
839 | 628 | Function to calculate the value of variable date_discount,amount_discounted,cash_discount,amount_difference | ||
840 | 629 | return the values as dictionary | ||
841 | 630 | """ | ||
842 | 631 | |||
843 | 632 | if context is None: | ||
844 | 633 | context = {} | ||
845 | 634 | invoice_obj = self.pool.get('account.invoice') | ||
846 | 635 | move_line_obj = self.pool.get('account.move.line') | ||
847 | 636 | voucher_line = self.browse(cr, uid, ids) | ||
848 | 637 | vch = self.pool.get('account.voucher').browse(cr, uid, voucher_line[0].voucher_id.id) | ||
849 | 638 | res = {} | ||
850 | 639 | for line in voucher_line: | ||
851 | 640 | if line.type == 'dr': | ||
852 | 641 | res[line.id] = { | ||
853 | 642 | 'date_discount': '', | ||
854 | 643 | 'amount_discounted': line.amount, | ||
855 | 644 | 'cash_discount': 0.0, | ||
856 | 645 | 'amount_difference': line.amount_unreconciled - line.amount , | ||
857 | 646 | } | ||
858 | 647 | continue | ||
859 | 648 | move_line = move_line_obj.browse(cr, uid, line.move_line_id.id) | ||
860 | 649 | invoice_number = move_line.name or move_line.ref | ||
861 | 650 | invoice_id = False | ||
862 | 651 | if invoice_number and invoice_number != '/': | ||
863 | 652 | invoice_id = invoice_obj.search(cr, uid, [('number', '=', str(invoice_number))]) | ||
864 | 653 | if not invoice_id: | ||
865 | 654 | move = self.pool.get('account.move').browse(cr, uid, move_line.move_id.id) | ||
866 | 655 | if move: | ||
867 | 656 | invoice_number = move.name or move.ref | ||
868 | 657 | if invoice_number and invoice_number != '/': | ||
869 | 658 | invoice_id = invoice_obj.search(cr, uid, [('number', '=', str(invoice_number))]) | ||
870 | 659 | if invoice_id: | ||
871 | 660 | for invoice in invoice_obj.browse(cr, uid, invoice_id, context): | ||
872 | 661 | date_discount = invoice.date_due | ||
873 | 662 | amount_discounted = invoice.amount_total | ||
874 | 663 | res[line.id] = { | ||
875 | 664 | 'date_discount': invoice.date_due, | ||
876 | 665 | 'amount_discounted': invoice.amount_total | ||
877 | 666 | } | ||
878 | 667 | if not invoice.date_invoice: | ||
879 | 668 | invoice_date = mx.DateTime.today().strftime("%Y-%m-%d") | ||
880 | 669 | self.write(cr, uid, [invoice.id], {'date_invoice': invoice_date}, context) | ||
881 | 670 | else: | ||
882 | 671 | invoice_date = invoice.date_invoice | ||
883 | 672 | discounts = invoice.payment_term and invoice.payment_term.get_discounts(invoice_date, context=context) or False | ||
884 | 673 | if discounts: | ||
885 | 674 | line_obj = self.pool.get('account.invoice.line') | ||
886 | 675 | discount_total = 0.0 | ||
887 | 676 | non_discount_total = 0.0 | ||
888 | 677 | for invline in invoice.invoice_line: | ||
889 | 678 | if invline.cash_discount: | ||
890 | 679 | discount_total += invline.price_subtotal | ||
891 | 680 | line_cash_discount = round((1.0 - discounts[0][1]) * invline.price_subtotal) | ||
892 | 681 | line_obj.write(cr, uid, invline.id, {'cash_discount': line_cash_discount}, context) | ||
893 | 682 | else: | ||
894 | 683 | non_discount_total += invline.price_subtotal | ||
895 | 684 | line_obj.write(cr, uid, invline.id, {'cash_discount': 0.0}, context) | ||
896 | 685 | # assume taxes are never discountable | ||
897 | 686 | non_discount_total += invoice.amount_tax | ||
898 | 687 | # There may be more than one - return the earliest | ||
899 | 688 | date_discount = discounts[0][0] | ||
900 | 689 | amount_discounted = round(((1.0 - discounts[0][1]) * discount_total) + non_discount_total,2) | ||
901 | 690 | amount_discount = 0.0 | ||
902 | 691 | if line.amount >= line.amount_unreconciled or line.amount < 0.01: | ||
903 | 692 | amount_discount = 0.0 | ||
904 | 693 | elif vch.date <= date_discount and line.amount <= line.amount_unreconciled: | ||
905 | 694 | amount_discount = max(line.amount_unreconciled - amount_discounted, 0.0) | ||
906 | 695 | elif vch.date <= date_discount and line.amount < amount_discounted: | ||
907 | 696 | amount_discount = max(line.amount_unreconciled - amount_discounted,0.0) | ||
908 | 697 | else: | ||
909 | 698 | amount_discount = 0.0 | ||
910 | 699 | |||
911 | 700 | res[line.id] = { | ||
912 | 701 | 'date_discount': date_discount, | ||
913 | 702 | 'amount_discounted': amount_discounted, | ||
914 | 703 | 'cash_discount': amount_discount, | ||
915 | 704 | 'amount_difference': line.amount_unreconciled - line.amount - line.credit_used - line.discount_used - (line._columns.has_key('writeoff_amount') and line['writeoff_amount']),#- amount_discount | ||
916 | 705 | } | ||
917 | 706 | return defaultdict(type([]),res) | ||
918 | 707 | def _get_supp_discount(self, cr, uid, ids, field_name, args, context={}): | ||
919 | 708 | """ | ||
920 | 709 | Function to calculate the value of variable date_discount,amount_discounted,cash_discount,amount_difference | ||
921 | 710 | return the values as dictionary | ||
922 | 711 | """ | ||
923 | 712 | |||
924 | 713 | if context is None: | ||
925 | 714 | context = {} | ||
926 | 715 | invoice_obj = self.pool.get('account.invoice') | ||
927 | 716 | move_line_obj = self.pool.get('account.move.line') | ||
928 | 717 | voucher_line = self.browse(cr, uid, ids) | ||
929 | 718 | vch = self.pool.get('account.voucher').browse(cr, uid, voucher_line[0].voucher_id.id) | ||
930 | 719 | res = {} | ||
931 | 720 | for line in voucher_line: | ||
932 | 721 | if line.type == 'cr': | ||
933 | 722 | res[line.id] = { | ||
934 | 723 | 'date_discount': '', | ||
935 | 724 | 'amount_discounted': line.amount, | ||
936 | 725 | 'cash_discount': 0.0, | ||
937 | 726 | 'supp_amount_difference': line.amount_unreconciled - line.amount , | ||
938 | 727 | 'discount' : False | ||
939 | 728 | } | ||
940 | 729 | continue | ||
941 | 730 | move_line = move_line_obj.browse(cr, uid, line.move_line_id.id) | ||
942 | 731 | invoice_number = move_line.name or move_line.ref | ||
943 | 732 | invoice_id = False | ||
944 | 733 | if invoice_number and invoice_number != '/': | ||
945 | 734 | invoice_id = invoice_obj.search(cr, uid, [('number', '=', str(invoice_number))]) | ||
946 | 735 | if not invoice_id: | ||
947 | 736 | move = self.pool.get('account.move').browse(cr, uid, move_line.move_id.id) | ||
948 | 737 | if move: | ||
949 | 738 | invoice_number = move.name or move.ref | ||
950 | 739 | if invoice_number and invoice_number != '/': | ||
951 | 740 | invoice_id = invoice_obj.search(cr, uid, [('number', '=', str(invoice_number))]) | ||
952 | 741 | if invoice_id: | ||
953 | 742 | for invoice in invoice_obj.browse(cr, uid, invoice_id, context): | ||
954 | 743 | date_discount = invoice.date_due | ||
955 | 744 | amount_discounted = invoice.amount_total | ||
956 | 745 | res[line.id] = { | ||
957 | 746 | 'date_discount': invoice.date_due, | ||
958 | 747 | 'supp_amount_difference': invoice.amount_total | ||
959 | 748 | } | ||
960 | 749 | if not invoice.date_invoice: | ||
961 | 750 | invoice_date = mx.DateTime.today().strftime("%Y-%m-%d") | ||
962 | 751 | self.write(cr, uid, [invoice.id], {'date_invoice': invoice_date}, context) | ||
963 | 752 | else: | ||
964 | 753 | invoice_date = invoice.date_invoice | ||
965 | 754 | discounts = invoice.payment_term and invoice.payment_term.get_discounts(invoice_date, context=context) or False | ||
966 | 755 | if discounts: | ||
967 | 756 | line_obj = self.pool.get('account.invoice.line') | ||
968 | 757 | discount_total = 0.0 | ||
969 | 758 | non_discount_total = 0.0 | ||
970 | 759 | for invline in invoice.invoice_line: | ||
971 | 760 | if invline.cash_discount: | ||
972 | 761 | discount_total += invline.price_subtotal | ||
973 | 762 | line_cash_discount = round((1.0 - discounts[0][1]) * invline.price_subtotal) | ||
974 | 763 | line_obj.write(cr, uid, invline.id, {'cash_discount': line_cash_discount}, context) | ||
975 | 764 | else: | ||
976 | 765 | non_discount_total += invline.price_subtotal | ||
977 | 766 | line_obj.write(cr, uid, invline.id, {'cash_discount': 0.0}, context) | ||
978 | 767 | # assume taxes are never discountable | ||
979 | 768 | non_discount_total += invoice.amount_tax | ||
980 | 769 | # There may be more than one - return the earliest | ||
981 | 770 | date_discount = discounts[0][0] | ||
982 | 771 | amount_discounted = round(((1.0 - discounts[0][1]) * discount_total) + non_discount_total,2) | ||
983 | 772 | amount_discount = 0.0 | ||
984 | 773 | if line.amount >= line.amount_unreconciled or line.amount < 0.01: | ||
985 | 774 | amount_discount = 0.0 | ||
986 | 775 | elif vch.date <= date_discount and line.amount <= line.amount_unreconciled: | ||
987 | 776 | amount_discount = max(line.amount_unreconciled - amount_discounted, 0.0) | ||
988 | 777 | elif vch.date <= date_discount and line.amount < amount_discounted: | ||
989 | 778 | amount_discount = max(line.amount_unreconciled - amount_discounted,0.0) | ||
990 | 779 | else: | ||
991 | 780 | amount_discount = 0.0 | ||
992 | 781 | discount=False | ||
993 | 782 | if line.available_discounts: | ||
994 | 783 | # if line.discount_used: | ||
995 | 784 | discount=True | ||
996 | 785 | res[line.id] = { | ||
997 | 786 | 'date_discount': date_discount, | ||
998 | 787 | 'amount_discounted': amount_discounted, | ||
999 | 788 | 'cash_discount': amount_discount, | ||
1000 | 789 | 'supp_amount_difference': line.amount_unreconciled - line.amount - line.credit_used - line.discount_used - (line._columns.has_key('writeoff_amount') and line['writeoff_amount']),#- amount_discount | ||
1001 | 790 | 'discount':discount | ||
1002 | 791 | } | ||
1003 | 792 | return defaultdict(type([]),res) | ||
1004 | 793 | |||
1005 | 794 | |||
1006 | 795 | _columns = { | ||
1007 | 796 | 'date_discount': fields.function(_get_discount, method=True, type='date', string='Discount Date', | ||
1008 | 797 | multi='all'), | ||
1009 | 798 | 'amount_discounted': fields.function(_get_discount, method=True, type='float', digits_compute=dp.get_precision('Account'), string='Discounted Total', | ||
1010 | 799 | multi='all'), | ||
1011 | 800 | 'cash_discount': fields.function(_get_discount, method=True, type='float', multi="all", digits_compute=dp.get_precision('Account'), string='Cash Discount',sequence=20), | ||
1012 | 801 | 'amount_difference': fields.function(_get_discount, method=True, multi='all', type='float', string='Unpaid Amt', digits=(16, 2) ), | ||
1013 | 802 | 'supp_amount_difference': fields.function(_get_supp_discount, method=True, multi='all', type='float', string='Unpaid Amt', digits=(16, 2) ), | ||
1014 | 803 | 'interest': fields.float(string='Interest', digits=(16,2)), | ||
1015 | 804 | |||
1016 | 805 | #'discount_used':fields.float('Discount used', readonly=True), | ||
1017 | 806 | 'discount_used': fields.function(_compute_discount_used, method=True, type='float', string='Discount Used', store=False, readonly=True,sequence=10), | ||
1018 | 807 | 'available_discounts':fields.one2many('account.voucher.line.discount_to_use', 'voucher_line_id', 'Available Discounts' ), | ||
1019 | 808 | 'discount': fields.function(_get_supp_discount, method=True, multi='all', type='boolean', string='Discount', readonly=True, sequence=20) | ||
1020 | 809 | } | ||
1021 | 810 | def clear_values(self, cr, uid, ids, context={}): | ||
1022 | 811 | ''' | ||
1023 | 812 | Clear the selected credits, discounts and writeoffs from voucher line | ||
1024 | 813 | ''' | ||
1025 | 814 | voucher_line = self.browse(cr,uid,ids[0]) | ||
1026 | 815 | if voucher_line._columns.has_key('writeoff_ids'): | ||
1027 | 816 | for lines in self.read(cr,uid,ids,['available_credits','writeoff_ids','available_discounts']): | ||
1028 | 817 | lines['writeoff_ids'] and self.pool.get('account.voucher.line.writeoff').unlink(cr,uid,lines['writeoff_ids']) | ||
1029 | 818 | lines['available_credits'] and self.pool.get('account.voucher.line.credits_to_use').write(cr,uid,lines['available_credits'],{ | ||
1030 | 819 | 'use_credit':False, | ||
1031 | 820 | 'discount_amount':0.0}) | ||
1032 | 821 | lines['available_discounts'] and self.pool.get('account.voucher.line.discount_to_use').write(cr,uid,lines['available_discounts'],{ | ||
1033 | 822 | 'use_discount':False, | ||
1034 | 823 | 'discount_amount':0.0}) | ||
1035 | 824 | else: | ||
1036 | 825 | for lines in self.read(cr,uid,ids,['available_credits','writeoff_ids','available_discounts']): | ||
1037 | 826 | lines['available_credits'] and self.pool.get('account.voucher.line.credits_to_use').write(cr,uid,lines['available_credits'],{ | ||
1038 | 827 | 'use_credit':False, | ||
1039 | 828 | 'discount_amount':0.0}) | ||
1040 | 829 | lines['available_discounts'] and self.pool.get('account.voucher.line.discount_to_use').write(cr,uid,lines['available_discounts'],{ | ||
1041 | 830 | 'use_discount':False, | ||
1042 | 831 | 'discount_amount':0.0}) | ||
1043 | 832 | return True | ||
1044 | 833 | account_voucher_line() | ||
1045 | 834 | |||
1046 | 835 | class product_product(osv.osv): | ||
1047 | 836 | ''' | ||
1048 | 837 | Add new account configuration fields to product | ||
1049 | 838 | ''' | ||
1050 | 839 | _name = "product.product" | ||
1051 | 840 | _inherit = 'product.product' | ||
1052 | 841 | _columns = { | ||
1053 | 842 | 'cash_discount': fields.boolean('Cash Discount?'), | ||
1054 | 843 | 'purchase_discount_account': fields.many2one('account.account', 'Purchase Discount Account', domain=[('user_type','=','COGS')]), | ||
1055 | 844 | 'sales_discount_account': fields.many2one('account.account', 'Sales Discount Account', domain=[('type','!=','view'),('type','!=','consolidation'),('user_type','ilike','income')]), | ||
1056 | 845 | 'purchase_discount_journal': fields.many2one('account.journal', 'Purchase Discount Journal', domain=[('type','!=','view'),('type','!=','consolidation'),('type','=','purchase')]), | ||
1057 | 846 | 'sales_discount_journal': fields.many2one('account.journal', 'Sales Discount Journal', domain=[('type','=','sale')]), | ||
1058 | 847 | } | ||
1059 | 848 | _defaults = { | ||
1060 | 849 | 'cash_discount' : lambda *a : True, | ||
1061 | 850 | } | ||
1062 | 851 | product_product() | ||
1063 | 852 | |||
1064 | 853 | class account_invoice_line(osv.osv): | ||
1065 | 854 | ''' | ||
1066 | 855 | option to disable discount calculation per invoice line | ||
1067 | 856 | ''' | ||
1068 | 857 | _name = 'account.invoice.line' | ||
1069 | 858 | _inherit = 'account.invoice.line' | ||
1070 | 859 | _columns = { | ||
1071 | 860 | 'cash_discount': fields.boolean('Cash Discount?'), | ||
1072 | 861 | } | ||
1073 | 862 | _defaults = { | ||
1074 | 863 | 'cash_discount' : lambda *a : True, | ||
1075 | 864 | } | ||
1076 | 865 | def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, address_invoice_id=False, currency_id=False, context=None): | ||
1077 | 866 | ''' | ||
1078 | 867 | check if the discount is applicable to newly selected product | ||
1079 | 868 | ''' | ||
1080 | 869 | result = {} | ||
1081 | 870 | result = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition_id, price_unit, address_invoice_id, currency_id, context) | ||
1082 | 871 | if product: | ||
1083 | 872 | res = self.pool.get('product.product').browse(cr, uid, product, context=context) | ||
1084 | 873 | result['value']['cash_discount'] = res.cash_discount | ||
1085 | 874 | else: | ||
1086 | 875 | result['value']['cash_discount'] = True | ||
1087 | 876 | return result | ||
1088 | 877 | account_invoice_line() | ||
1089 | 878 | |||
1090 | 879 | class res_company(osv.osv): | ||
1091 | 880 | ''' | ||
1092 | 881 | New account configuration fields on copmany form | ||
1093 | 882 | ''' | ||
1094 | 883 | _name = 'res.company' | ||
1095 | 884 | _inherit = 'res.company' | ||
1096 | 885 | _columns = { | ||
1097 | 886 | 'purchase_discount_account': fields.many2one('account.account', 'Purchase Discount Account', domain=[('user_type','=','COGS'),('type','!=','view'),('type','!=','consolidation')]), | ||
1098 | 887 | 'sales_discount_account': fields.many2one('account.account', 'Sales Discount Account', domain=[('user_type','=','Income'),('type','!=','view'),('type','!=','consolidation')]), | ||
1099 | 888 | 'purchase_discount_journal': fields.many2one('account.journal', 'Purchase Discount Journal', domain=[('type','=','purchase')]), | ||
1100 | 889 | 'sales_discount_journal': fields.many2one('account.journal', 'Sales Discount Journal', domain=[('type','=','sale')]), | ||
1101 | 890 | } | ||
1102 | 891 | res_company() | ||
1103 | 892 | |||
1104 | 893 | class account_voucher_line_discount_to_use(osv.osv): | ||
1105 | 894 | ''' | ||
1106 | 895 | Dynamically generated discount lines that are applicable per voucher line | ||
1107 | 896 | ''' | ||
1108 | 897 | _name = "account.voucher.line.discount_to_use" | ||
1109 | 898 | _rec_name = 'inv_credit' | ||
1110 | 899 | _columns = { | ||
1111 | 900 | 'voucher_line_id': fields.many2one('account.voucher.line', 'Account Voucher Line', ondelete='cascade', readonly=True), | ||
1112 | 901 | 'use_discount': fields.boolean('Use Discount',help='Used to indicate if the cash discount should be used/taken when calculating payment.', required=True), | ||
1113 | 902 | 'inv_payment_terms': fields.many2one('account.payment.term', 'Invoice Payment Terms', help='Payments terms description', ), | ||
1114 | 903 | 'discount_window_date': fields.date('Discount Window Date',help='The last day of the discount window. To receive discounts payments must be paid on or before this date.'), | ||
1115 | 904 | |||
1116 | 905 | |||
1117 | 906 | 'proposed_discount': fields.float('Proposed Discount',help='This is the proposed full discount based on the Invoice Payment Terms and the Original Amount.', readonly=True), | ||
1118 | 907 | 'discount_amount': fields.float('Discount Amt',help='Enter the amount of discount to be given.', required=True), | ||
1119 | 908 | 'gl_account' : fields.many2one('account.account', 'G/L Account',help='Enter the General Ledger account number to record taking the cash discount.', required=True), | ||
1120 | 909 | } | ||
1121 | 910 | def onchage_use_discount(self, cr, uid, ids, use_discount, proposed_discount, context=None): | ||
1122 | 911 | ''' | ||
1123 | 912 | Fill the value with proposed discount when use discount check box is clicked and remove the value when use discount is unchecked | ||
1124 | 913 | ''' | ||
1125 | 914 | res = {} | ||
1126 | 915 | if use_discount: | ||
1127 | 916 | res['value'] = {'discount_amount': proposed_discount} | ||
1128 | 917 | else: | ||
1129 | 918 | res['value'] = {'discount_amount': 0} | ||
1130 | 919 | return res | ||
1131 | 920 | def onchage_discount_amount(self, cr, uid, ids, proposed_discount, discount_amount, context=None): | ||
1132 | 921 | ''' | ||
1133 | 922 | Function to check discount amount entered in discount line of payment line | ||
1134 | 923 | ''' | ||
1135 | 924 | res = {} | ||
1136 | 925 | if discount_amount < 0: | ||
1137 | 926 | res['value'] = {'discount_amount': 0, 'use_discount':False } | ||
1138 | 927 | res['warning'] = {'title': 'Discount not in the limit', 'message': 'Discount should not be a negative value.'} | ||
1139 | 928 | return res | ||
1140 | 929 | if discount_amount > proposed_discount: | ||
1141 | 930 | res['value'] = {'discount_amount': proposed_discount, 'use_discount':True } | ||
1142 | 931 | res['warning'] = {'title': 'Discount not in the limit', 'message': 'Please adjust the Discount Amt value to be less than or equal the Proposed Discount.'} | ||
1143 | 932 | return res | ||
1144 | 933 | if discount_amount == 0.0: | ||
1145 | 934 | res['value'] = { 'use_discount':False } | ||
1146 | 935 | else: | ||
1147 | 936 | res['value'] = { 'use_discount':True } | ||
1148 | 937 | return res | ||
1149 | 938 | account_voucher_line_discount_to_use() | ||
1150 | 939 | |||
1151 | 940 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
1152 | 941 | |||
1153 | 0 | 942 | ||
1154 | === added directory 'account_cash_discount_us/account_cash_discount_us' | |||
1155 | === added file 'account_cash_discount_us/account_cash_discount_us/Change Log.txt' | |||
1156 | --- account_cash_discount_us/account_cash_discount_us/Change Log.txt 1970-01-01 00:00:00 +0000 | |||
1157 | +++ account_cash_discount_us/account_cash_discount_us/Change Log.txt 2011-10-06 15:23:28 +0000 | |||
1158 | @@ -0,0 +1,31 @@ | |||
1159 | 1 | =============================================================================== | ||
1160 | 2 | Version Change Log (account_cash_discount_us) | ||
1161 | 3 | =============================================================================== | ||
1162 | 4 | |||
1163 | 5 | 1.07 -> 1.08 (2011-02-04) By Sinoj | ||
1164 | 6 | * Optimization and cleanup | ||
1165 | 7 | |||
1166 | 8 | 1.06 -> 1.07 (2010-12-06) By jabir | ||
1167 | 9 | * Removed discount wizard and changed domain filtering | ||
1168 | 10 | |||
1169 | 11 | 1.05 -> 1.06 (2010-12-06) By jabir | ||
1170 | 12 | * Take invoice partner instead of moveline partner | ||
1171 | 13 | |||
1172 | 14 | 1.04 -> 1.05 (2010-11-29) By Jabir | ||
1173 | 15 | * Fix placement of Cash Discount Separation Line | ||
1174 | 16 | |||
1175 | 17 | 1.03 -> 1.04 (2010-11-29) By Sinoj | ||
1176 | 18 | * Account posting updated for National account | ||
1177 | 19 | |||
1178 | 20 | 1.02 -> 1.03 (2010-11-09) By Sinoj | ||
1179 | 21 | * "Debit and Credits" wizard button moved to voucher line | ||
1180 | 22 | * fields on wizard form are readonly | ||
1181 | 23 | * fields on wizard are populated with default values | ||
1182 | 24 | * removed | ||
1183 | 25 | |||
1184 | 26 | 1.01 -> 1.02 (2010-11-04) By jabir | ||
1185 | 27 | * Add wizard Discount and Credits | ||
1186 | 28 | * Create button Discount and Credits in customer payment form | ||
1187 | 29 | |||
1188 | 30 | 1.0 -> 1.01 (2010-11-04) By sinoj | ||
1189 | 31 | * dependency changed from account_voucher_jdc to account_voucher_credits_us | ||
1190 | 0 | \ No newline at end of file | 32 | \ No newline at end of file |
1191 | 1 | 33 | ||
1192 | === added file 'account_cash_discount_us/account_cash_discount_us/__init__.py' | |||
1193 | --- account_cash_discount_us/account_cash_discount_us/__init__.py 1970-01-01 00:00:00 +0000 | |||
1194 | +++ account_cash_discount_us/account_cash_discount_us/__init__.py 2011-10-06 15:23:28 +0000 | |||
1195 | @@ -0,0 +1,26 @@ | |||
1196 | 1 | # -*- coding: utf-8 -*- | ||
1197 | 2 | ############################################################################## | ||
1198 | 3 | # | ||
1199 | 4 | # OpenERP, Open Source Management Solution | ||
1200 | 5 | # Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>) | ||
1201 | 6 | # Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>) | ||
1202 | 7 | # | ||
1203 | 8 | # This program is free software: you can redistribute it and/or modify | ||
1204 | 9 | # it under the terms of the GNU General Public License as published by | ||
1205 | 10 | # the Free Software Foundation, either version 3 of the License, or | ||
1206 | 11 | # (at your option) any later version. | ||
1207 | 12 | # | ||
1208 | 13 | # This program is distributed in the hope that it will be useful, | ||
1209 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1210 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1211 | 16 | # GNU General Public License for more details. | ||
1212 | 17 | # | ||
1213 | 18 | # You should have received a copy of the GNU General Public License | ||
1214 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/> | ||
1215 | 20 | # | ||
1216 | 21 | ############################################################################## | ||
1217 | 22 | |||
1218 | 23 | |||
1219 | 24 | import account_cash_discount | ||
1220 | 25 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
1221 | 26 | |||
1222 | 0 | 27 | ||
1223 | === added file 'account_cash_discount_us/account_cash_discount_us/__openerp__.py' | |||
1224 | --- account_cash_discount_us/account_cash_discount_us/__openerp__.py 1970-01-01 00:00:00 +0000 | |||
1225 | +++ account_cash_discount_us/account_cash_discount_us/__openerp__.py 2011-10-06 15:23:28 +0000 | |||
1226 | @@ -0,0 +1,54 @@ | |||
1227 | 1 | # -*- coding: utf-8 -*- | ||
1228 | 2 | ############################################################################## | ||
1229 | 3 | # | ||
1230 | 4 | # OpenERP, Open Source Management Solution | ||
1231 | 5 | # Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>) | ||
1232 | 6 | # Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>) | ||
1233 | 7 | # | ||
1234 | 8 | # This program is free software: you can redistribute it and/or modify | ||
1235 | 9 | # it under the terms of the GNU General Public License as published by | ||
1236 | 10 | # the Free Software Foundation, either version 3 of the License, or | ||
1237 | 11 | # (at your option) any later version. | ||
1238 | 12 | # | ||
1239 | 13 | # This program is distributed in the hope that it will be useful, | ||
1240 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1241 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1242 | 16 | # GNU General Public License for more details. | ||
1243 | 17 | # | ||
1244 | 18 | # You should have received a copy of the GNU General Public License | ||
1245 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/> | ||
1246 | 20 | # | ||
1247 | 21 | ############################################################################## | ||
1248 | 22 | |||
1249 | 23 | |||
1250 | 24 | { | ||
1251 | 25 | "name" : "Payment Term with Cash Discount", | ||
1252 | 26 | "version" : "1.08", | ||
1253 | 27 | "depends" : ["account","account_voucher_credits_us","account_cash_discount"], | ||
1254 | 28 | "author" : "Tiny and NovaPoint Group LLC", | ||
1255 | 29 | "description" : "Cash discounts, based on payment terms", | ||
1256 | 30 | "website" : "http://www.novapointgroup.com/", | ||
1257 | 31 | "category" : "Generic Modules/Accounting", | ||
1258 | 32 | "description": """ | ||
1259 | 33 | This module adds cash discounts on payment terms. Cash discounts | ||
1260 | 34 | for a payment term can be configured with: | ||
1261 | 35 | * A number of days, | ||
1262 | 36 | * A discount (%), | ||
1263 | 37 | * A debit and a credit account | ||
1264 | 38 | * Sales and Purchase discounts are added to product and invoice line | ||
1265 | 39 | """, | ||
1266 | 40 | "init_xml" : [ | ||
1267 | 41 | ], | ||
1268 | 42 | "demo_xml" : [ | ||
1269 | 43 | ], | ||
1270 | 44 | "update_xml" : [ | ||
1271 | 45 | "account_cash_discount_view.xml", | ||
1272 | 46 | "product_view.xml", | ||
1273 | 47 | "security/ir.model.access.csv", | ||
1274 | 48 | ], | ||
1275 | 49 | "active": False, | ||
1276 | 50 | "installable": True, | ||
1277 | 51 | |||
1278 | 52 | } | ||
1279 | 53 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
1280 | 54 | |||
1281 | 0 | 55 | ||
1282 | === added file 'account_cash_discount_us/account_cash_discount_us/__terp__.py' | |||
1283 | --- account_cash_discount_us/account_cash_discount_us/__terp__.py 1970-01-01 00:00:00 +0000 | |||
1284 | +++ account_cash_discount_us/account_cash_discount_us/__terp__.py 2011-10-06 15:23:28 +0000 | |||
1285 | @@ -0,0 +1,52 @@ | |||
1286 | 1 | # -*- encoding: utf-8 -*- | ||
1287 | 2 | ############################################################################## | ||
1288 | 3 | # | ||
1289 | 4 | # OpenERP, Open Source Management Solution | ||
1290 | 5 | # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). | ||
1291 | 6 | # | ||
1292 | 7 | # This program is free software: you can redistribute it and/or modify | ||
1293 | 8 | # it under the terms of the GNU Affero General Public License as | ||
1294 | 9 | # published by the Free Software Foundation, either version 3 of the | ||
1295 | 10 | # License, or (at your option) any later version. | ||
1296 | 11 | # | ||
1297 | 12 | # This program is distributed in the hope that it will be useful, | ||
1298 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1299 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1300 | 15 | # GNU Affero General Public License for more details. | ||
1301 | 16 | # | ||
1302 | 17 | # You should have received a copy of the GNU Affero General Public License | ||
1303 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1304 | 19 | # | ||
1305 | 20 | ############################################################################## | ||
1306 | 21 | |||
1307 | 22 | { | ||
1308 | 23 | "name" : "Payment Term with Cash Discount", | ||
1309 | 24 | "version" : "1.07", | ||
1310 | 25 | "depends" : ["account","account_voucher_credits_us","account_cash_discount"], | ||
1311 | 26 | "author" : "Tiny and NovaPoint Group LLC", | ||
1312 | 27 | "description" : "Cash discounts, based on payment terms", | ||
1313 | 28 | "website" : "http://www.novapointgroup.com/", | ||
1314 | 29 | "category" : "Generic Modules/Accounting", | ||
1315 | 30 | "description": """ | ||
1316 | 31 | This module adds cash discounts on payment terms. Cash discounts | ||
1317 | 32 | for a payment term can be configured with: | ||
1318 | 33 | * A number of days, | ||
1319 | 34 | * A discount (%), | ||
1320 | 35 | * A debit and a credit account | ||
1321 | 36 | * Sales and Purchase discounts are added to product and invoice line | ||
1322 | 37 | """, | ||
1323 | 38 | "init_xml" : [ | ||
1324 | 39 | ], | ||
1325 | 40 | "demo_xml" : [ | ||
1326 | 41 | ], | ||
1327 | 42 | "update_xml" : [ | ||
1328 | 43 | "account_cash_discount_view.xml", | ||
1329 | 44 | "product_view.xml", | ||
1330 | 45 | "security/ir.model.access.csv", | ||
1331 | 46 | ], | ||
1332 | 47 | "active": False, | ||
1333 | 48 | "installable": True, | ||
1334 | 49 | |||
1335 | 50 | } | ||
1336 | 51 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
1337 | 52 | |||
1338 | 0 | 53 | ||
1339 | === added file 'account_cash_discount_us/account_cash_discount_us/account_cash_discount.py' | |||
1340 | --- account_cash_discount_us/account_cash_discount_us/account_cash_discount.py 1970-01-01 00:00:00 +0000 | |||
1341 | +++ account_cash_discount_us/account_cash_discount_us/account_cash_discount.py 2011-10-06 15:23:28 +0000 | |||
1342 | @@ -0,0 +1,730 @@ | |||
1343 | 1 | # -*- coding: utf-8 -*- | ||
1344 | 2 | ############################################################################## | ||
1345 | 3 | # | ||
1346 | 4 | # OpenERP, Open Source Management Solution | ||
1347 | 5 | # Copyright (C) 2011 NovaPoint Group LLC (<http://www.novapointgroup.com>) | ||
1348 | 6 | # Copyright (C) 2004-2010 OpenERP SA (<http://www.openerp.com>) | ||
1349 | 7 | # | ||
1350 | 8 | # This program is free software: you can redistribute it and/or modify | ||
1351 | 9 | # it under the terms of the GNU General Public License as published by | ||
1352 | 10 | # the Free Software Foundation, either version 3 of the License, or | ||
1353 | 11 | # (at your option) any later version. | ||
1354 | 12 | # | ||
1355 | 13 | # This program is distributed in the hope that it will be useful, | ||
1356 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1357 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1358 | 16 | # GNU General Public License for more details. | ||
1359 | 17 | # | ||
1360 | 18 | # You should have received a copy of the GNU General Public License | ||
1361 | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/> | ||
1362 | 20 | # | ||
1363 | 21 | ############################################################################## | ||
1364 | 22 | |||
1365 | 23 | from collections import defaultdict | ||
1366 | 24 | from mx.DateTime import RelativeDateTime | ||
1367 | 25 | from osv import fields, osv | ||
1368 | 26 | from tools.translate import _ | ||
1369 | 27 | import decimal_precision as dp | ||
1370 | 28 | import mx.DateTime | ||
1371 | 29 | |||
1372 | 30 | def _combinations(iterable, r): | ||
1373 | 31 | ''' | ||
1374 | 32 | @return: combination generator object | ||
1375 | 33 | |||
1376 | 34 | Example | ||
1377 | 35 | combinations(’ABCD’, 2) --> AB AC AD BC BD CD | ||
1378 | 36 | combinations(range(4), 3) --> 012 013 023 123 | ||
1379 | 37 | ''' | ||
1380 | 38 | pool = tuple(iterable) | ||
1381 | 39 | n = len(pool) | ||
1382 | 40 | if r > n: | ||
1383 | 41 | return | ||
1384 | 42 | indices = range(r) | ||
1385 | 43 | yield tuple(pool[i] for i in indices) | ||
1386 | 44 | while True: | ||
1387 | 45 | for i in reversed(range(r)): | ||
1388 | 46 | if indices[i] != i + n - r: | ||
1389 | 47 | break | ||
1390 | 48 | else: | ||
1391 | 49 | return | ||
1392 | 50 | indices[i] += 1 | ||
1393 | 51 | for j in range(i+1, r): | ||
1394 | 52 | indices[j] = indices[j-1] + 1 | ||
1395 | 53 | yield tuple(pool[i] for i in indices) | ||
1396 | 54 | |||
1397 | 55 | |||
1398 | 56 | class account_payment_term(osv.osv): | ||
1399 | 57 | _name = "account.payment.term" | ||
1400 | 58 | _inherit = "account.payment.term" | ||
1401 | 59 | _columns = { | ||
1402 | 60 | 'cash_discount_ids': fields.one2many('account.cash.discount', 'payment_id', 'Cash Discounts'), | ||
1403 | 61 | } | ||
1404 | 62 | def get_discounts(self, cr, uid, id, base_date, context={}): | ||
1405 | 63 | """ | ||
1406 | 64 | return the list of (date,percentage) ordered by date for the | ||
1407 | 65 | payment term with the corresponding id. return [] if no cash | ||
1408 | 66 | discount are defined. base_date is the date from where the | ||
1409 | 67 | discounts are computed. | ||
1410 | 68 | """ | ||
1411 | 69 | res=[] | ||
1412 | 70 | for pt in self.browse(cr, uid, id, context): | ||
1413 | 71 | |||
1414 | 72 | if not pt.cash_discount_ids: | ||
1415 | 73 | continue | ||
1416 | 74 | |||
1417 | 75 | for d in pt.cash_discount_ids: | ||
1418 | 76 | res.append( | ||
1419 | 77 | ((mx.DateTime.strptime(base_date,'%Y-%m-%d') +\ | ||
1420 | 78 | RelativeDateTime(days=d.delay)).strftime("%Y-%m-%d"), | ||
1421 | 79 | d.discount) | ||
1422 | 80 | ) | ||
1423 | 81 | |||
1424 | 82 | res.sort(cmp=lambda x,y: cmp(x[0],y[0])) | ||
1425 | 83 | return res | ||
1426 | 84 | account_payment_term() | ||
1427 | 85 | |||
1428 | 86 | class account_invoice(osv.osv): | ||
1429 | 87 | ''' | ||
1430 | 88 | Add discount calculation to invoice | ||
1431 | 89 | ''' | ||
1432 | 90 | _inherit = 'account.invoice' | ||
1433 | 91 | |||
1434 | 92 | def _get_discount(self, cr, uid, ids, field_name, args, context={}): | ||
1435 | 93 | ''' | ||
1436 | 94 | Calculate the value of variable date_discount (Discount Date) and amount_discounted (Discounted Total) | ||
1437 | 95 | ''' | ||
1438 | 96 | |||
1439 | 97 | if context is None: | ||
1440 | 98 | context = {} | ||
1441 | 99 | for invoice in self.browse(cr, uid, ids, context): | ||
1442 | 100 | res = defaultdict(list) | ||
1443 | 101 | res[invoice.id] = { | ||
1444 | 102 | 'date_discount': invoice.date_due, | ||
1445 | 103 | 'amount_discounted': invoice.amount_total | ||
1446 | 104 | } | ||
1447 | 105 | if not invoice.date_invoice: | ||
1448 | 106 | invoice_date = mx.DateTime.today().strftime("%Y-%m-%d") | ||
1449 | 107 | self.write(cr, uid, [invoice.id], {'date_invoice': invoice_date}, context) | ||
1450 | 108 | else: | ||
1451 | 109 | invoice_date = invoice.date_invoice | ||
1452 | 110 | discounts = invoice.payment_term and invoice.payment_term.get_discounts(invoice_date, context=context) | ||
1453 | 111 | if discounts: | ||
1454 | 112 | line_obj = self.pool.get('account.invoice.line') | ||
1455 | 113 | discount_total = 0.0 | ||
1456 | 114 | non_discount_total = 0.0 | ||
1457 | 115 | for line in invoice.invoice_line: | ||
1458 | 116 | if line.cash_discount: | ||
1459 | 117 | discount_total += line.price_subtotal | ||
1460 | 118 | line_cash_discount = round((1.0 - discounts[0][1]) * line.price_subtotal) | ||
1461 | 119 | line_obj.write(cr, uid, line.id, {'cash_discount': line_cash_discount}, context) | ||
1462 | 120 | else: | ||
1463 | 121 | non_discount_total += line.price_subtotal | ||
1464 | 122 | line_obj.write(cr, uid, line.id, {'cash_discount': 0.0}, context) | ||
1465 | 123 | # assume taxes are never discountable | ||
1466 | 124 | non_discount_total += invoice.amount_tax | ||
1467 | 125 | # There may be more than one - return the earliest | ||
1468 | 126 | res[invoice.id] = { | ||
1469 | 127 | 'date_discount': discounts[0][0], | ||
1470 | 128 | 'amount_discounted': round(((1.0 - discounts[0][1]) * discount_total) + non_discount_total,2) | ||
1471 | 129 | } | ||
1472 | 130 | return defaultdict(type([]),res) | ||
1473 | 131 | |||
1474 | 132 | _columns = { | ||
1475 | 133 | 'date_discount': fields.function(_get_discount, method=True, type='date', string='Discount Date', multi='all'), | ||
1476 | 134 | 'amount_discounted': fields.function(_get_discount, method=True, type='float', digits_compute=dp.get_precision('Account'), string='Discounted Total', | ||
1477 | 135 | multi='all'), | ||
1478 | 136 | } | ||
1479 | 137 | account_invoice() | ||
1480 | 138 | |||
1481 | 139 | class account_invoice_pay_writeoff(osv.osv_memory): | ||
1482 | 140 | """ | ||
1483 | 141 | Opens the write off amount pay form. | ||
1484 | 142 | """ | ||
1485 | 143 | _name = "account.invoice.pay.writeoff" | ||
1486 | 144 | _description = "Pay Invoice " | ||
1487 | 145 | _columns = { | ||
1488 | 146 | 'writeoff_acc_id': fields.many2one('account.account', 'Write-Off account', required=True), | ||
1489 | 147 | 'writeoff_journal_id': fields.many2one('account.journal', 'Write-Off journal', required=True), | ||
1490 | 148 | 'comment': fields.char('Comment', size=64, required=True), | ||
1491 | 149 | 'analytic_id': fields.many2one('account.analytic.account','Analytic Account'), | ||
1492 | 150 | } | ||
1493 | 151 | _defaults = { | ||
1494 | 152 | 'comment': 'Write-Off', | ||
1495 | 153 | } | ||
1496 | 154 | |||
1497 | 155 | account_invoice_pay_writeoff() | ||
1498 | 156 | |||
1499 | 157 | class account_invoice_pay(osv.osv_memory): | ||
1500 | 158 | """ | ||
1501 | 159 | Generate pay invoice wizard, user can make partial or full payment for invoice. | ||
1502 | 160 | """ | ||
1503 | 161 | _name = "account.invoice.pay" | ||
1504 | 162 | _description = "Pay Invoice " | ||
1505 | 163 | _columns = { | ||
1506 | 164 | 'amount': fields.float('Amount paid', required=True, digits_compute = dp.get_precision('Account')), | ||
1507 | 165 | 'name': fields.char('Entry Name', size=64, required=True), | ||
1508 | 166 | 'date': fields.date('Date payment', required=True), | ||
1509 | 167 | 'journal_id': fields.many2one('account.journal', 'Journal/Payment Mode', required=True, domain=[('type','=','cash')]), | ||
1510 | 168 | 'period_id': fields.many2one('account.period', 'Period', required=True), | ||
1511 | 169 | } | ||
1512 | 170 | |||
1513 | 171 | def view_init(self, cr, uid, ids, context=None): | ||
1514 | 172 | invoice = self.pool.get('account.invoice').browse(cr, uid, context['active_id'], context=context) | ||
1515 | 173 | if invoice.state in ['draft', 'proforma2', 'cancel']: | ||
1516 | 174 | raise osv.except_osv(_('Error !'), _('Can not pay draft/proforma/cancel invoice.')) | ||
1517 | 175 | pass | ||
1518 | 176 | |||
1519 | 177 | def _get_period(self, cr, uid, context=None): | ||
1520 | 178 | ''' | ||
1521 | 179 | Initialise Period | ||
1522 | 180 | ''' | ||
1523 | 181 | ids = self.pool.get('account.period').find(cr, uid, context=context) | ||
1524 | 182 | period_id = False | ||
1525 | 183 | if len(ids): | ||
1526 | 184 | period_id = ids[0] | ||
1527 | 185 | return period_id | ||
1528 | 186 | |||
1529 | 187 | def _get_amount(self, cr, uid, context=None): | ||
1530 | 188 | ''' | ||
1531 | 189 | Get default value of Amount paid | ||
1532 | 190 | ''' | ||
1533 | 191 | return self.pool.get('account.invoice').browse(cr, uid, context['active_id'], context=context).residual | ||
1534 | 192 | |||
1535 | 193 | _defaults = { | ||
1536 | 194 | 'date': lambda *a: time.strftime('%Y-%m-%d'), | ||
1537 | 195 | 'period_id': _get_period, | ||
1538 | 196 | 'amount': _get_amount, | ||
1539 | 197 | } | ||
1540 | 198 | account_invoice_pay() | ||
1541 | 199 | |||
1542 | 200 | class account_voucher(osv.osv): | ||
1543 | 201 | _name = 'account.voucher' | ||
1544 | 202 | _inherit = 'account.voucher' | ||
1545 | 203 | |||
1546 | 204 | def _update_discounts(self, lines, vch_date): | ||
1547 | 205 | date_discount = False | ||
1548 | 206 | amount_discount = False | ||
1549 | 207 | for line in lines: | ||
1550 | 208 | if 'date_discount' in line: | ||
1551 | 209 | date_discount = line['date_discount'] | ||
1552 | 210 | amount_discounted = line['amount_discounted'] | ||
1553 | 211 | else: | ||
1554 | 212 | return | ||
1555 | 213 | if line['amount'] >= line['amount_unreconciled']: | ||
1556 | 214 | amount_discount = 0.0 | ||
1557 | 215 | elif vch_date <= date_discount and line['amount'] <= line['amount_unreconciled'] and line['amount'] >= amount_discounted: | ||
1558 | 216 | amount_discount = max(line['amount_unreconciled'] - amount_discounted, 0.0) | ||
1559 | 217 | elif vch_date <= date_discount and line['amount'] < amount_discounted: | ||
1560 | 218 | amount_discount = max(line['amount_unreconciled'] - amount_discounted, 0.0) | ||
1561 | 219 | line['cash_discount'] = amount_discount | ||
1562 | 220 | line['amount_difference'] = line['amount_unreconciled'] - line['amount'] - amount_discount | ||
1563 | 221 | |||
1564 | 222 | |||
1565 | 223 | def onchange_partner_id(self, cr, uid, ids, partner_id, journal_id, price, currency_id, ttype, date, context={}): | ||
1566 | 224 | ''' | ||
1567 | 225 | Function to update fields in customer payment form on changing customer | ||
1568 | 226 | ''' | ||
1569 | 227 | if context is None: | ||
1570 | 228 | context = {} | ||
1571 | 229 | |||
1572 | 230 | currency_pool = self.pool.get('res.currency') | ||
1573 | 231 | journal_pool = self.pool.get('account.journal') | ||
1574 | 232 | invoice_pool = self.pool.get('account.invoice') | ||
1575 | 233 | line_pool = self.pool.get('account.voucher.line') | ||
1576 | 234 | move_line_pool = self.pool.get('account.move.line') | ||
1577 | 235 | partner_pool = self.pool.get('res.partner') | ||
1578 | 236 | company_currency = False | ||
1579 | 237 | |||
1580 | 238 | default = super(account_voucher, self).onchange_partner_id(cr, uid, ids, partner_id, journal_id, price, currency_id, ttype, date, context={}) | ||
1581 | 239 | if not partner_id: | ||
1582 | 240 | return default | ||
1583 | 241 | # we have to clear out lines, because new lines will be created by the change | ||
1584 | 242 | if partner_id and not journal_id: | ||
1585 | 243 | partner = partner_pool.browse(cr, uid, partner_id, context) | ||
1586 | 244 | if partner._columns.has_key('payment_meth_id') and partner.payment_meth_id: | ||
1587 | 245 | payment_mode_pool = self.pool.get('payment.mode') | ||
1588 | 246 | payment_meth = payment_mode_pool.browse(cr, uid, partner.payment_meth_id.id, context) | ||
1589 | 247 | if payment_meth: | ||
1590 | 248 | default['value']['journal_id'] = payment_meth.journal.id | ||
1591 | 249 | journal_id = payment_meth.journal.id | ||
1592 | 250 | if ids: | ||
1593 | 251 | line_ids = line_pool.search(cr, uid, [('voucher_id','=',ids[0])]) | ||
1594 | 252 | if line_ids: | ||
1595 | 253 | line_pool.unlink(cr, uid, line_ids) | ||
1596 | 254 | if journal_id: | ||
1597 | 255 | journal = journal_pool.browse(cr, uid, journal_id) | ||
1598 | 256 | company_currency = journal.company_id.currency_id.id | ||
1599 | 257 | |||
1600 | 258 | total_credit = 0.0 | ||
1601 | 259 | total_debit = 0.0 | ||
1602 | 260 | vch_date = False | ||
1603 | 261 | for vch in self.browse(cr, uid, ids): | ||
1604 | 262 | vch_date = vch.date | ||
1605 | 263 | if default and 'value' in default and 'line_cr_ids' in default['value']: | ||
1606 | 264 | for line in default['value']['line_cr_ids']: | ||
1607 | 265 | invoice_id = invoice_pool.search(cr, uid, [('number', '=', line['name'])]) | ||
1608 | 266 | if invoice_id: | ||
1609 | 267 | line['invoice_id'] = invoice_id[0] | ||
1610 | 268 | invoice = invoice_pool.browse(cr, uid, invoice_id[0], ) | ||
1611 | 269 | date_discount = invoice.date_discount | ||
1612 | 270 | amount_discounted = invoice.amount_discounted | ||
1613 | 271 | line['date_discount'] = date_discount | ||
1614 | 272 | line['amount_discounted'] = amount_discounted | ||
1615 | 273 | else: | ||
1616 | 274 | line['date_discount'] = False | ||
1617 | 275 | line['amount_discounted'] = 0.0 | ||
1618 | 276 | line['amount'] = 0.0 | ||
1619 | 277 | total_credit += line['type'] == 'cr' and line['amount_unreconciled'] or 0.0 | ||
1620 | 278 | total_debit += line['type'] == 'dr' and line['amount_unreconciled'] or 0.0 | ||
1621 | 279 | # first, see if we can find an invoice matching the amount to be applied | ||
1622 | 280 | found = False | ||
1623 | 281 | def calc_amount(line, total): | ||
1624 | 282 | return min(line['amount_unreconciled'], total) | ||
1625 | 283 | lines = default['value']['line_cr_ids'] | ||
1626 | 284 | if len(lines) == 0: | ||
1627 | 285 | return default | ||
1628 | 286 | # return False | ||
1629 | 287 | # if only one, assign it | ||
1630 | 288 | if len(lines) == 1: | ||
1631 | 289 | for line in lines: | ||
1632 | 290 | if line['type'] == 'cr': | ||
1633 | 291 | amount = price | ||
1634 | 292 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, amount) or amount | ||
1635 | 293 | total_credit -= amount | ||
1636 | 294 | found = True | ||
1637 | 295 | break | ||
1638 | 296 | else: | ||
1639 | 297 | amount = price | ||
1640 | 298 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, amount) or amount | ||
1641 | 299 | total_debit -= amount | ||
1642 | 300 | found = True | ||
1643 | 301 | break | ||
1644 | 302 | self._update_discounts(lines, vch_date) | ||
1645 | 303 | if not found: | ||
1646 | 304 | for line in lines: | ||
1647 | 305 | if line['amount_unreconciled'] == price: | ||
1648 | 306 | if line['type'] == 'cr': | ||
1649 | 307 | amount = calc_amount(line, total_credit) | ||
1650 | 308 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, amount) or amount | ||
1651 | 309 | total_credit -= amount | ||
1652 | 310 | found = True | ||
1653 | 311 | break | ||
1654 | 312 | else: | ||
1655 | 313 | amount = calc_amount(line, total_debit) | ||
1656 | 314 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, amount) or amount | ||
1657 | 315 | total_debit -= amount | ||
1658 | 316 | found = True | ||
1659 | 317 | break | ||
1660 | 318 | if not found: | ||
1661 | 319 | # see if we can find a combination that matches | ||
1662 | 320 | def search(lines, price): | ||
1663 | 321 | for i in range(0, len(lines)): | ||
1664 | 322 | if lines[i]['amount_unreconciled'] == price: | ||
1665 | 323 | return [lines[i]] | ||
1666 | 324 | for i in range(0, len(lines)): | ||
1667 | 325 | for j in range(i + 1, len(lines)): | ||
1668 | 326 | if lines[i]['amount_unreconciled'] + lines[j]['amount_unreconciled'] == price: | ||
1669 | 327 | return [lines[i],lines[j]] | ||
1670 | 328 | for i in range(0, len(lines)): | ||
1671 | 329 | for j in range(i + 1, len(lines)): | ||
1672 | 330 | for k in range(j + 1, len(lines)): | ||
1673 | 331 | if lines[i]['amount_unreconciled'] + lines[j]['amount_unreconciled'] + lines[k]['amount_unreconciled']== price: | ||
1674 | 332 | return [lines[i],lines[j],lines[k]] | ||
1675 | 333 | line_ids = search(lines, price) | ||
1676 | 334 | |||
1677 | 335 | if line_ids: # and sum == price: | ||
1678 | 336 | for line in line_ids: | ||
1679 | 337 | if line['type'] == 'cr': | ||
1680 | 338 | amount = calc_amount(line, line['amount_unreconciled']) | ||
1681 | 339 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, amount) | ||
1682 | 340 | total_debit -= amount | ||
1683 | 341 | found = True | ||
1684 | 342 | else: | ||
1685 | 343 | amount = calc_amount(line, line['amount_unreconciled']) | ||
1686 | 344 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, amount) | ||
1687 | 345 | total_credit -= amount | ||
1688 | 346 | found = True | ||
1689 | 347 | if not found: | ||
1690 | 348 | # see if we can find a match using discounted amount | ||
1691 | 349 | def search2(lines, price): | ||
1692 | 350 | for i in range(0, len(lines)): | ||
1693 | 351 | if min(lines[i]['amount_unreconciled'],lines[i]['amount_discounted']) == price: | ||
1694 | 352 | return [lines[i]] | ||
1695 | 353 | for i in range(0, len(lines)): | ||
1696 | 354 | for j in range(i + 1, len(lines)): | ||
1697 | 355 | if min(lines[i]['amount_unreconciled'],lines[i]['amount_discounted']) + min(lines[j]['amount_unreconciled'],lines[j]['amount_discounted']) == price: | ||
1698 | 356 | return [lines[i],lines[j]] | ||
1699 | 357 | for i in range(0, len(lines)): | ||
1700 | 358 | for j in range(i + 1, len(lines)): | ||
1701 | 359 | for k in range(j + 1, len(lines)): | ||
1702 | 360 | if min(lines[i]['amount_unreconciled'],lines[i]['amount_discounted']) + min(lines[j]['amount_unreconciled'],lines[j]['amount_discounted']) + min(lines[k]['amount_unreconciled'],lines[k]['amount_discounted']) == price: | ||
1703 | 361 | return [lines[i],lines[j],lines[k]] | ||
1704 | 362 | line_ids = search(lines, price) | ||
1705 | 363 | lines = default['value']['line_cr_ids'] | ||
1706 | 364 | line_ids = search2(lines, price) | ||
1707 | 365 | if line_ids: | ||
1708 | 366 | for line in line_ids: | ||
1709 | 367 | if line['type'] == 'cr': | ||
1710 | 368 | amount = calc_amount(line, min(line['amount_unreconciled'],line['amount_discounted'])) | ||
1711 | 369 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, min(line['amount_unreconciled'],line['amount_discounted'])) | ||
1712 | 370 | total_debit -= amount | ||
1713 | 371 | found = True | ||
1714 | 372 | else: | ||
1715 | 373 | amount = calc_amount(line, min(line['amount_unreconciled'],line['amount_discounted'])) | ||
1716 | 374 | line['amount'] = currency_pool.compute(cr, uid, company_currency, currency_id, min(line['amount_unreconciled'],line['amount_discounted'])) | ||
1717 | 375 | total_credit -= amount | ||
1718 | 376 | found = True | ||
1719 | 377 | lines = default['value']['line_cr_ids'] | ||
1720 | 378 | ''' | ||
1721 | 379 | FIXME : removing amount from line_dr_ids (Credits on customer payment form) line. | ||
1722 | 380 | and amount from line_cr_ids (Invoice and outstanding transactions on customer payment form) line | ||
1723 | 381 | I do not think this this is a good solution. But it works. | ||
1724 | 382 | The whole "onchange_partner_id" function need a re-thinking (may have to rewrite it completely instead of calling super ). | ||
1725 | 383 | ''' | ||
1726 | 384 | if default: | ||
1727 | 385 | for credit_line in default['value'].get('line_dr_ids',[]): | ||
1728 | 386 | credit_line['amount'] = 0.0 | ||
1729 | 387 | for invoce_line in default['value'].get('line_cr_ids',[]): | ||
1730 | 388 | invoce_line['amount'] = 0.0 | ||
1731 | 389 | invoce_line['amount_difference'] = invoce_line['amount_unreconciled'] | ||
1732 | 390 | return default | ||
1733 | 391 | |||
1734 | 392 | def calc_cash_discount(self, cr, uid, ids, vch, line, context={}): | ||
1735 | 393 | ''' | ||
1736 | 394 | Calculate discount per line | ||
1737 | 395 | ''' | ||
1738 | 396 | total_allocated = 0.0 | ||
1739 | 397 | for line in vch.line_ids: | ||
1740 | 398 | total_allocated += line.amount | ||
1741 | 399 | context.update({'total_allocated': total_allocated, 'total_amount': vch.date}) | ||
1742 | 400 | amount_discount = 0.0 | ||
1743 | 401 | if line.amount >= line.amount_unreconciled or line.amount < 0.01 : | ||
1744 | 402 | amount_discount = 0.0 | ||
1745 | 403 | elif line.amount >= line.amount_discounted and vch.date <= line.date_discount: | ||
1746 | 404 | amount_discount = line.amount_unreconciled - line.amount_discounted | ||
1747 | 405 | return amount_discount | ||
1748 | 406 | |||
1749 | 407 | account_voucher() | ||
1750 | 408 | |||
1751 | 409 | class account_voucher_line(osv.osv): | ||
1752 | 410 | _name = 'account.voucher.line' | ||
1753 | 411 | _inherit = 'account.voucher.line' | ||
1754 | 412 | |||
1755 | 413 | def _update_credit_lines(self,cr, uid, ids, context): | ||
1756 | 414 | ''' | ||
1757 | 415 | Function to update the credit lines in payment lines | ||
1758 | 416 | ''' | ||
1759 | 417 | credits_used_pool = self.pool.get('account.voucher.line.credits_to_use') | ||
1760 | 418 | for line in self.browse(cr , uid, ids, context): | ||
1761 | 419 | credits_lines_used = [x.orginal_credit_line_id.id for x in line.available_credits] | ||
1762 | 420 | for credit_line in line.voucher_id.line_dr_ids : | ||
1763 | 421 | if credit_line.id not in credits_lines_used and line.invoice_id and line.invoice_id.payment_term: | ||
1764 | 422 | print credit_line | ||
1765 | 423 | credits_used_pool.create(cr, uid, { | ||
1766 | 424 | 'voucher_line_id': line.id, | ||
1767 | 425 | 'orginal_credit_line_id':credit_line.id, | ||
1768 | 426 | 'use_credit': False, | ||
1769 | 427 | 'inv_credit': credit_line.move_line_id.id, | ||
1770 | 428 | 'discount_window_date': credit_line.date_original, | ||
1771 | 429 | 'orginal_amount': credit_line.amount_original, | ||
1772 | 430 | 'available_amount': credit_line.amount_unreconciled - credit_line.pending_credits, | ||
1773 | 431 | 'discount_amount': 0.0, | ||
1774 | 432 | 'gl_account' : credit_line.account_id.id,}) | ||
1775 | 433 | else : | ||
1776 | 434 | to_update_credit_line_ids = credits_used_pool.search(cr,uid,[('voucher_line_id','=',line.id),( 'orginal_credit_line_id','=',credit_line.id)], context=context) | ||
1777 | 435 | if to_update_credit_line_ids: | ||
1778 | 436 | credits_used_pool.write(cr, uid,to_update_credit_line_ids,{'available_amount': credit_line.amount_unreconciled-credit_line.pending_credits}, context=context) | ||
1779 | 437 | |||
1780 | 438 | def _update_discount_lines(self,cr, uid, ids, context): | ||
1781 | 439 | ''' | ||
1782 | 440 | Function to update the discount lines in payment lines | ||
1783 | 441 | ''' | ||
1784 | 442 | |||
1785 | 443 | discount_used_pool = self.pool.get('account.voucher.line.discount_to_use') | ||
1786 | 444 | user_pool = self.pool.get('res.users') | ||
1787 | 445 | user = user_pool.browse(cr, uid, uid, context) | ||
1788 | 446 | for line in self.browse(cr , uid, ids, context): | ||
1789 | 447 | if line.invoice_id : | ||
1790 | 448 | if not line.invoice_id.date_discount or not line.voucher_id.date or line.voucher_id.date > line.invoice_id.date_discount: | ||
1791 | 449 | ''' | ||
1792 | 450 | customer is not eligible for the discount | ||
1793 | 451 | ''' | ||
1794 | 452 | continue | ||
1795 | 453 | discount = line.invoice_id.amount_total - line.invoice_id.amount_discounted | ||
1796 | 454 | date_discount = line.invoice_id.date_discount | ||
1797 | 455 | discount_found = False | ||
1798 | 456 | for discount_line in line.available_discounts: | ||
1799 | 457 | #if abs(discount - discount_line.proposed_discount) < 0.01 and line.invoice_id.payment_term.id == discount_line.inv_payment_terms.id: | ||
1800 | 458 | if line.invoice_id.payment_term.id == discount_line.inv_payment_terms.id: | ||
1801 | 459 | discount_found = True | ||
1802 | 460 | continue | ||
1803 | 461 | if not discount_found and user.company_id.sales_discount_account: | ||
1804 | 462 | ''' | ||
1805 | 463 | TODO : calculate/findout the discount_window_date (The last day of the discount window. To receive discounts payments must be paid on or before this date.) | ||
1806 | 464 | ''' | ||
1807 | 465 | discount_used_pool.create(cr, uid, { | ||
1808 | 466 | 'voucher_line_id': line.id, | ||
1809 | 467 | 'use_discount': False, | ||
1810 | 468 | 'inv_payment_terms':line.invoice_id.payment_term.id , | ||
1811 | 469 | 'discount_window_date': date_discount, | ||
1812 | 470 | 'proposed_discount': discount, | ||
1813 | 471 | 'discount_amount': 0.0, | ||
1814 | 472 | 'gl_account':user.company_id.sales_discount_account.id | ||
1815 | 473 | }, context=context) | ||
1816 | 474 | |||
1817 | 475 | |||
1818 | 476 | def _compute_discount_used(self, cr, uid, ids, name, args, context=None): | ||
1819 | 477 | ''' | ||
1820 | 478 | Function to calculate the value of variable discount used | ||
1821 | 479 | ''' | ||
1822 | 480 | res = {} | ||
1823 | 481 | for line in self.browse(cr, uid, ids): | ||
1824 | 482 | res[line.id] = 0.0 | ||
1825 | 483 | for discount_line in line.available_discounts: | ||
1826 | 484 | if discount_line.use_discount : | ||
1827 | 485 | res[line.id] += discount_line.discount_amount | ||
1828 | 486 | return res | ||
1829 | 487 | |||
1830 | 488 | def _compute_balance(self, cr, uid, ids, name, args, context=None): | ||
1831 | 489 | ''' | ||
1832 | 490 | Function to calculate the value of variables Cash Discount, Interest and Amt Due | ||
1833 | 491 | ''' | ||
1834 | 492 | currency_pool = self.pool.get('res.currency') | ||
1835 | 493 | rs_data = super(account_voucher_line, self)._compute_balance(cr, uid, ids, name, args, context) | ||
1836 | 494 | for line in self.browse(cr, uid, ids): | ||
1837 | 495 | amount_cash_discount = self.calc_cash_discount(cr, uid, ids, vch, line) | ||
1838 | 496 | amount_interest = self.calc_interest(vch, line, line.amount) | ||
1839 | 497 | amount_unreconciled = 0.0 | ||
1840 | 498 | move_line = line.move_line_id or False | ||
1841 | 499 | if move_line: | ||
1842 | 500 | amount_unreconciled = currency_pool.compute(cr, uid, company_currency, voucher_currency, move_line.amount_unreconciled - amount_cash_discount - line.writeoff) | ||
1843 | 501 | rs_data[line.id] = {'cash_discount': amount_cash_discount, 'interest': amount_interest, 'amount_unreconciled': amount_unreconciled} | ||
1844 | 502 | return rs_data | ||
1845 | 503 | |||
1846 | 504 | def _get_discount(self, cr, uid, ids, field_name, args, context={}): | ||
1847 | 505 | """ | ||
1848 | 506 | Function to calculate the value of variable date_discount,amount_discounted,cash_discount,amount_difference | ||
1849 | 507 | return the values as dictionary | ||
1850 | 508 | """ | ||
1851 | 509 | |||
1852 | 510 | if context is None: | ||
1853 | 511 | context = {} | ||
1854 | 512 | invoice_obj = self.pool.get('account.invoice') | ||
1855 | 513 | move_line_obj = self.pool.get('account.move.line') | ||
1856 | 514 | voucher_line = self.browse(cr, uid, ids) | ||
1857 | 515 | vch = self.pool.get('account.voucher').browse(cr, uid, voucher_line[0].voucher_id.id) | ||
1858 | 516 | res = {} | ||
1859 | 517 | for line in voucher_line: | ||
1860 | 518 | if line.type == 'dr': | ||
1861 | 519 | res[line.id] = { | ||
1862 | 520 | 'date_discount': '', | ||
1863 | 521 | 'amount_discounted': line.amount, | ||
1864 | 522 | 'cash_discount': 0.0, | ||
1865 | 523 | 'amount_difference': line.amount_unreconciled - line.amount | ||
1866 | 524 | } | ||
1867 | 525 | continue | ||
1868 | 526 | move_line = move_line_obj.browse(cr, uid, line.move_line_id.id) | ||
1869 | 527 | invoice_number = move_line.name or move_line.ref | ||
1870 | 528 | invoice_id = False | ||
1871 | 529 | if invoice_number and invoice_number != '/': | ||
1872 | 530 | invoice_id = invoice_obj.search(cr, uid, [('number', '=', str(invoice_number))]) | ||
1873 | 531 | if not invoice_id: | ||
1874 | 532 | move = self.pool.get('account.move').browse(cr, uid, move_line.move_id.id) | ||
1875 | 533 | if move: | ||
1876 | 534 | invoice_number = move.name or move.ref | ||
1877 | 535 | if invoice_number and invoice_number != '/': | ||
1878 | 536 | invoice_id = invoice_obj.search(cr, uid, [('number', '=', str(invoice_number))]) | ||
1879 | 537 | if invoice_id: | ||
1880 | 538 | for invoice in invoice_obj.browse(cr, uid, invoice_id, context): | ||
1881 | 539 | date_discount = invoice.date_due | ||
1882 | 540 | amount_discounted = invoice.amount_total | ||
1883 | 541 | res[line.id] = { | ||
1884 | 542 | 'date_discount': invoice.date_due, | ||
1885 | 543 | 'amount_discounted': invoice.amount_total | ||
1886 | 544 | } | ||
1887 | 545 | if not invoice.date_invoice: | ||
1888 | 546 | invoice_date = mx.DateTime.today().strftime("%Y-%m-%d") | ||
1889 | 547 | self.write(cr, uid, [invoice.id], {'date_invoice': invoice_date}, context) | ||
1890 | 548 | else: | ||
1891 | 549 | invoice_date = invoice.date_invoice | ||
1892 | 550 | discounts = invoice.payment_term and invoice.payment_term.get_discounts(invoice_date, context=context) or False | ||
1893 | 551 | if discounts: | ||
1894 | 552 | line_obj = self.pool.get('account.invoice.line') | ||
1895 | 553 | discount_total = 0.0 | ||
1896 | 554 | non_discount_total = 0.0 | ||
1897 | 555 | for invline in invoice.invoice_line: | ||
1898 | 556 | if invline.cash_discount: | ||
1899 | 557 | discount_total += invline.price_subtotal | ||
1900 | 558 | line_cash_discount = round((1.0 - discounts[0][1]) * invline.price_subtotal) | ||
1901 | 559 | line_obj.write(cr, uid, invline.id, {'cash_discount': line_cash_discount}, context) | ||
1902 | 560 | else: | ||
1903 | 561 | non_discount_total += invline.price_subtotal | ||
1904 | 562 | line_obj.write(cr, uid, invline.id, {'cash_discount': 0.0}, context) | ||
1905 | 563 | # assume taxes are never discountable | ||
1906 | 564 | non_discount_total += invoice.amount_tax | ||
1907 | 565 | # There may be more than one - return the earliest | ||
1908 | 566 | date_discount = discounts[0][0] | ||
1909 | 567 | amount_discounted = round(((1.0 - discounts[0][1]) * discount_total) + non_discount_total,2) | ||
1910 | 568 | amount_discount = 0.0 | ||
1911 | 569 | if line.amount >= line.amount_unreconciled or line.amount < 0.01: | ||
1912 | 570 | amount_discount = 0.0 | ||
1913 | 571 | elif vch.date <= date_discount and line.amount <= line.amount_unreconciled: | ||
1914 | 572 | amount_discount = max(line.amount_unreconciled - amount_discounted, 0.0) | ||
1915 | 573 | elif vch.date <= date_discount and line.amount < amount_discounted: | ||
1916 | 574 | amount_discount = max(line.amount_unreconciled - amount_discounted,0.0) | ||
1917 | 575 | else: | ||
1918 | 576 | amount_discount = 0.0 | ||
1919 | 577 | |||
1920 | 578 | res[line.id] = { | ||
1921 | 579 | 'date_discount': date_discount, | ||
1922 | 580 | 'amount_discounted': amount_discounted, | ||
1923 | 581 | 'cash_discount': amount_discount, | ||
1924 | 582 | 'amount_difference': line.amount_unreconciled - line.amount - line.credit_used - line.discount_used - (line._columns.has_key('writeoff_amount') and line['writeoff_amount'])#- amount_discount | ||
1925 | 583 | } | ||
1926 | 584 | return defaultdict(type([]),res) | ||
1927 | 585 | |||
1928 | 586 | _columns = { | ||
1929 | 587 | 'date_discount': fields.function(_get_discount, method=True, type='date', string='Discount Date', | ||
1930 | 588 | multi='all'), | ||
1931 | 589 | 'amount_discounted': fields.function(_get_discount, method=True, type='float', digits_compute=dp.get_precision('Account'), string='Discounted Total', | ||
1932 | 590 | multi='all'), | ||
1933 | 591 | 'cash_discount': fields.function(_get_discount, method=True, type='float', multi="all", digits_compute=dp.get_precision('Account'), string='Cash Discount'), | ||
1934 | 592 | 'amount_difference': fields.function(_get_discount, method=True, multi='all', type='float', string='Unpaid Amt', digits=(16, 2) ), | ||
1935 | 593 | 'interest': fields.float(string='Interest', digits=(16,2)), | ||
1936 | 594 | |||
1937 | 595 | #'discount_used':fields.float('Discount used', readonly=True), | ||
1938 | 596 | 'discount_used': fields.function(_compute_discount_used, method=True, type='float', string='Discount Used', store=False, readonly=True), | ||
1939 | 597 | 'available_discounts':fields.one2many('account.voucher.line.discount_to_use', 'voucher_line_id', 'Available Discounts' ), | ||
1940 | 598 | } | ||
1941 | 599 | def clear_values(self, cr, uid, ids, context={}): | ||
1942 | 600 | ''' | ||
1943 | 601 | Clear the selected credits, discounts and writeoffs from voucher line | ||
1944 | 602 | ''' | ||
1945 | 603 | voucher_line = self.browse(cr,uid,ids[0]) | ||
1946 | 604 | if voucher_line._columns.has_key('writeoff_ids'): | ||
1947 | 605 | for lines in self.read(cr,uid,ids,['available_credits','writeoff_ids','available_discounts']): | ||
1948 | 606 | lines['writeoff_ids'] and self.pool.get('account.voucher.line.writeoff').unlink(cr,uid,lines['writeoff_ids']) | ||
1949 | 607 | lines['available_credits'] and self.pool.get('account.voucher.line.credits_to_use').write(cr,uid,lines['available_credits'],{ | ||
1950 | 608 | 'use_credit':False, | ||
1951 | 609 | 'discount_amount':0.0}) | ||
1952 | 610 | lines['available_discounts'] and self.pool.get('account.voucher.line.discount_to_use').write(cr,uid,lines['available_discounts'],{ | ||
1953 | 611 | 'use_discount':False, | ||
1954 | 612 | 'discount_amount':0.0}) | ||
1955 | 613 | else: | ||
1956 | 614 | for lines in self.read(cr,uid,ids,['available_credits','writeoff_ids','available_discounts']): | ||
1957 | 615 | lines['available_credits'] and self.pool.get('account.voucher.line.credits_to_use').write(cr,uid,lines['available_credits'],{ | ||
1958 | 616 | 'use_credit':False, | ||
1959 | 617 | 'discount_amount':0.0}) | ||
1960 | 618 | lines['available_discounts'] and self.pool.get('account.voucher.line.discount_to_use').write(cr,uid,lines['available_discounts'],{ | ||
1961 | 619 | 'use_discount':False, | ||
1962 | 620 | 'discount_amount':0.0}) | ||
1963 | 621 | return True | ||
1964 | 622 | account_voucher_line() | ||
1965 | 623 | |||
1966 | 624 | class product_product(osv.osv): | ||
1967 | 625 | ''' | ||
1968 | 626 | Add new account configuration fields to product | ||
1969 | 627 | ''' | ||
1970 | 628 | _name = "product.product" | ||
1971 | 629 | _inherit = 'product.product' | ||
1972 | 630 | _columns = { | ||
1973 | 631 | 'cash_discount': fields.boolean('Cash Discount?'), | ||
1974 | 632 | 'purchase_discount_account': fields.many2one('account.account', 'Purchase Discount Account', domain=[('user_type','=','COGS')]), | ||
1975 | 633 | 'sales_discount_account': fields.many2one('account.account', 'Sales Discount Account', domain=[('type','!=','view'),('type','!=','consolidation'),('user_type','ilike','income')]), | ||
1976 | 634 | 'purchase_discount_journal': fields.many2one('account.journal', 'Purchase Discount Journal', domain=[('type','!=','view'),('type','!=','consolidation'),('type','=','purchase')]), | ||
1977 | 635 | 'sales_discount_journal': fields.many2one('account.journal', 'Sales Discount Journal', domain=[('type','=','sale')]), | ||
1978 | 636 | } | ||
1979 | 637 | _defaults = { | ||
1980 | 638 | 'cash_discount' : lambda *a : True, | ||
1981 | 639 | } | ||
1982 | 640 | product_product() | ||
1983 | 641 | |||
1984 | 642 | class account_invoice_line(osv.osv): | ||
1985 | 643 | ''' | ||
1986 | 644 | option to disable discount calculation per invoice line | ||
1987 | 645 | ''' | ||
1988 | 646 | _name = 'account.invoice.line' | ||
1989 | 647 | _inherit = 'account.invoice.line' | ||
1990 | 648 | _columns = { | ||
1991 | 649 | 'cash_discount': fields.boolean('Cash Discount?'), | ||
1992 | 650 | } | ||
1993 | 651 | _defaults = { | ||
1994 | 652 | 'cash_discount' : lambda *a : True, | ||
1995 | 653 | } | ||
1996 | 654 | def product_id_change(self, cr, uid, ids, product, uom, qty=0, name='', type='out_invoice', partner_id=False, fposition_id=False, price_unit=False, address_invoice_id=False, currency_id=False, context=None): | ||
1997 | 655 | ''' | ||
1998 | 656 | check if the discount is applicable to newly selected product | ||
1999 | 657 | ''' | ||
2000 | 658 | result = {} | ||
2001 | 659 | result = super(account_invoice_line, self).product_id_change(cr, uid, ids, product, uom, qty, name, type, partner_id, fposition_id, price_unit, address_invoice_id, currency_id, context) | ||
2002 | 660 | if product: | ||
2003 | 661 | res = self.pool.get('product.product').browse(cr, uid, product, context=context) | ||
2004 | 662 | result['value']['cash_discount'] = res.cash_discount | ||
2005 | 663 | else: | ||
2006 | 664 | result['value']['cash_discount'] = True | ||
2007 | 665 | return result | ||
2008 | 666 | account_invoice_line() | ||
2009 | 667 | |||
2010 | 668 | class res_company(osv.osv): | ||
2011 | 669 | ''' | ||
2012 | 670 | New account configuration fields on copmany form | ||
2013 | 671 | ''' | ||
2014 | 672 | _name = 'res.company' | ||
2015 | 673 | _inherit = 'res.company' | ||
2016 | 674 | _columns = { | ||
2017 | 675 | 'purchase_discount_account': fields.many2one('account.account', 'Purchase Discount Account', domain=[('user_type','=','COGS'),('type','!=','view'),('type','!=','consolidation')]), | ||
2018 | 676 | 'sales_discount_account': fields.many2one('account.account', 'Sales Discount Account', domain=[('user_type','=','Income'),('type','!=','view'),('type','!=','consolidation')]), | ||
2019 | 677 | 'purchase_discount_journal': fields.many2one('account.journal', 'Purchase Discount Journal', domain=[('type','=','purchase')]), | ||
2020 | 678 | 'sales_discount_journal': fields.many2one('account.journal', 'Sales Discount Journal', domain=[('type','=','sale')]), | ||
2021 | 679 | } | ||
2022 | 680 | res_company() | ||
2023 | 681 | |||
2024 | 682 | class account_voucher_line_discount_to_use(osv.osv): | ||
2025 | 683 | ''' | ||
2026 | 684 | Dynamically generated discount lines that are applicable per voucher line | ||
2027 | 685 | ''' | ||
2028 | 686 | _name = "account.voucher.line.discount_to_use" | ||
2029 | 687 | _rec_name = 'inv_credit' | ||
2030 | 688 | _columns = { | ||
2031 | 689 | 'voucher_line_id': fields.many2one('account.voucher.line', 'Account Voucher Line', ondelete='cascade', readonly=True), | ||
2032 | 690 | 'use_discount': fields.boolean('Use Discount',help='Used to indicate if the cash discount should be used/taken when calculating payment.', required=True), | ||
2033 | 691 | 'inv_payment_terms': fields.many2one('account.payment.term', 'Invoice Payment Terms', help='Payments terms description', ), | ||
2034 | 692 | 'discount_window_date': fields.date('Discount Window Date',help='The last day of the discount window. To receive discounts payments must be paid on or before this date.'), | ||
2035 | 693 | |||
2036 | 694 | |||
2037 | 695 | 'proposed_discount': fields.float('Proposed Discount',help='This is the proposed full discount based on the Invoice Payment Terms and the Original Amount.', readonly=True), | ||
2038 | 696 | 'discount_amount': fields.float('Discount Amt',help='Enter the amount of discount to be given.', required=True), | ||
2039 | 697 | 'gl_account' : fields.many2one('account.account', 'G/L Account',help='Enter the General Ledger account number to record taking the cash discount.', required=True), | ||
2040 | 698 | } | ||
2041 | 699 | def onchage_use_discount(self, cr, uid, ids, use_discount, proposed_discount, context=None): | ||
2042 | 700 | ''' | ||
2043 | 701 | Fill the value with proposed discount when use discount check box is clicked and remove the value when use discount is unchecked | ||
2044 | 702 | ''' | ||
2045 | 703 | res = {} | ||
2046 | 704 | if use_discount: | ||
2047 | 705 | res['value'] = {'discount_amount': proposed_discount} | ||
2048 | 706 | else: | ||
2049 | 707 | res['value'] = {'discount_amount': 0} | ||
2050 | 708 | return res | ||
2051 | 709 | def onchage_discount_amount(self, cr, uid, ids, proposed_discount, discount_amount, context=None): | ||
2052 | 710 | ''' | ||
2053 | 711 | Function to check discount amount entered in discount line of payment line | ||
2054 | 712 | ''' | ||
2055 | 713 | res = {} | ||
2056 | 714 | if discount_amount < 0: | ||
2057 | 715 | res['value'] = {'discount_amount': 0, 'use_discount':False } | ||
2058 | 716 | res['warning'] = {'title': 'Discount not in the limit', 'message': 'Discount should not be a negative value.'} | ||
2059 | 717 | return res | ||
2060 | 718 | if discount_amount > proposed_discount: | ||
2061 | 719 | res['value'] = {'discount_amount': proposed_discount, 'use_discount':True } | ||
2062 | 720 | res['warning'] = {'title': 'Discount not in the limit', 'message': 'Please adjust the Discount Amt value to be less than or equal the Proposed Discount.'} | ||
2063 | 721 | return res | ||
2064 | 722 | if discount_amount == 0.0: | ||
2065 | 723 | res['value'] = { 'use_discount':False } | ||
2066 | 724 | else: | ||
2067 | 725 | res['value'] = { 'use_discount':True } | ||
2068 | 726 | return res | ||
2069 | 727 | account_voucher_line_discount_to_use() | ||
2070 | 728 | |||
2071 | 729 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | ||
2072 | 730 | |||
2073 | 0 | 731 | ||
2074 | === added file 'account_cash_discount_us/account_cash_discount_us/account_cash_discount_view.xml' | |||
2075 | --- account_cash_discount_us/account_cash_discount_us/account_cash_discount_view.xml 1970-01-01 00:00:00 +0000 | |||
2076 | +++ account_cash_discount_us/account_cash_discount_us/account_cash_discount_view.xml 2011-10-06 15:23:28 +0000 | |||
2077 | @@ -0,0 +1,256 @@ | |||
2078 | 1 | <?xml version="1.0"?> | ||
2079 | 2 | <openerp> | ||
2080 | 3 | <data> | ||
2081 | 4 | |||
2082 | 5 | <!-- cash discount --> | ||
2083 | 6 | |||
2084 | 7 | <record id="invoice_supplier_form_jdc" model="ir.ui.view"> | ||
2085 | 8 | <field name="name">account.invoice.supplier.form.jdc</field> | ||
2086 | 9 | <field name="model">account.invoice</field> | ||
2087 | 10 | <field name="type">form</field> | ||
2088 | 11 | <field name="priority">2</field> | ||
2089 | 12 | <field name="inherit_id" ref="account.invoice_supplier_form"/> | ||
2090 | 13 | <field name="arch" type="xml"> | ||
2091 | 14 | <xpath expr="/form/notebook/page/field[@name='check_total']" position="after"> | ||
2092 | 15 | <field name="date_discount"/> | ||
2093 | 16 | <field name="amount_discounted"/> | ||
2094 | 17 | </xpath> | ||
2095 | 18 | </field> | ||
2096 | 19 | </record> | ||
2097 | 20 | <record id="invoice_form_jdc1" model="ir.ui.view"> | ||
2098 | 21 | <field name="name">account.invoice.form.jdc1</field> | ||
2099 | 22 | <field name="model">account.invoice</field> | ||
2100 | 23 | <field name="type">form</field> | ||
2101 | 24 | <field name="inherit_id" ref="account.invoice_form"/> | ||
2102 | 25 | <field name="arch" type="xml"> | ||
2103 | 26 | <xpath expr="/form/notebook/page[@string='Invoice']/field[@name='invoice_line']" position="before"> | ||
2104 | 27 | <group colspan="2" col="4"> | ||
2105 | 28 | <field name="date_discount"/> | ||
2106 | 29 | <field name="amount_discounted"/> | ||
2107 | 30 | </group> | ||
2108 | 31 | </xpath> | ||
2109 | 32 | </field> | ||
2110 | 33 | </record> | ||
2111 | 34 | |||
2112 | 35 | |||
2113 | 36 | <!-- | ||
2114 | 37 | Invoice Line | ||
2115 | 38 | --> | ||
2116 | 39 | <record id="view_invoice_line_form_discount" model="ir.ui.view"> | ||
2117 | 40 | <field name="name">account.invoice.line.form.discount</field> | ||
2118 | 41 | <field name="model">account.invoice.line</field> | ||
2119 | 42 | <field name="inherit_id" ref="account.view_invoice_line_form"/> | ||
2120 | 43 | <field name="type">form</field> | ||
2121 | 44 | <field name="arch" type="xml"> | ||
2122 | 45 | <xpath expr="/form/notebook/page/field[@name='discount']" position="after"> | ||
2123 | 46 | <field name="cash_discount"/> | ||
2124 | 47 | </xpath> | ||
2125 | 48 | </field> | ||
2126 | 49 | </record> | ||
2127 | 50 | |||
2128 | 51 | <!-- | ||
2129 | 52 | Products | ||
2130 | 53 | --> | ||
2131 | 54 | <record id="product_normal_form_view_discount" model="ir.ui.view"> | ||
2132 | 55 | <field name="name">product.normal.form.discount</field> | ||
2133 | 56 | <field name="model">product.product</field> | ||
2134 | 57 | <field name="type">form</field> | ||
2135 | 58 | <field eval="7" name="priority"/> | ||
2136 | 59 | <field name="inherit_id" ref="product.product_normal_form_view"/> | ||
2137 | 60 | <field name="arch" type="xml"> | ||
2138 | 61 | <xpath expr="/form/notebook/page[@string='Suppliers']/field[@name='seller_ids']" position="after"> | ||
2139 | 62 | <field name="cash_discount"/> | ||
2140 | 63 | </xpath> | ||
2141 | 64 | </field> | ||
2142 | 65 | </record> | ||
2143 | 66 | |||
2144 | 67 | <!-- | ||
2145 | 68 | Company | ||
2146 | 69 | --> | ||
2147 | 70 | <record id="view_company_form_jdc2" model="ir.ui.view"> | ||
2148 | 71 | <field name="name">res.company.form.jdc2</field> | ||
2149 | 72 | <field name="model">res.company</field> | ||
2150 | 73 | <field name="type">form</field> | ||
2151 | 74 | <field name="inherit_id" ref="account_voucher_credits_us.view_company_form_jdc3"/> | ||
2152 | 75 | <field name="priority" eval="1"/> | ||
2153 | 76 | <field name="arch" type="xml"> | ||
2154 | 77 | <xpath expr="/form/notebook/page[@string='Accounting']/field[@name='writeoff_account']" position="before"> | ||
2155 | 78 | <field name="sales_discount_account" colspan="2" /> | ||
2156 | 79 | <field name="purchase_discount_account" colspan="2" /> | ||
2157 | 80 | <field name="sales_discount_journal" colspan="2"/> | ||
2158 | 81 | <field name="purchase_discount_journal" colspan="2"/> | ||
2159 | 82 | </xpath> | ||
2160 | 83 | </field> | ||
2161 | 84 | </record> | ||
2162 | 85 | |||
2163 | 86 | <!-- Discount --> | ||
2164 | 87 | |||
2165 | 88 | <record model="ir.ui.view" id="view_account_wizard_discount_form"> | ||
2166 | 89 | <field name="name">account.wizard.discount.form</field> | ||
2167 | 90 | <field name="model">account.wizard.discount</field> | ||
2168 | 91 | <field name="type">form</field> | ||
2169 | 92 | <field name="arch" type="xml"> | ||
2170 | 93 | <form string="Discount"> | ||
2171 | 94 | <field name="use_discount" select="1"/> | ||
2172 | 95 | <field name="inv_payment_terms" select="1" readonly="1"/> | ||
2173 | 96 | <field name="discount_window_date" select="1"/> | ||
2174 | 97 | <field name="proposed_discount" select="1"/> | ||
2175 | 98 | <field name="discount_amount" select="1"/> | ||
2176 | 99 | <field name="gl_account" select="1"/> | ||
2177 | 100 | </form> | ||
2178 | 101 | </field> | ||
2179 | 102 | </record> | ||
2180 | 103 | |||
2181 | 104 | <record model="ir.ui.view" id="view_account_wizard_discount_tree"> | ||
2182 | 105 | <field name="name">account.wizard.discount.tree</field> | ||
2183 | 106 | <field name="model">account.wizard.discount</field> | ||
2184 | 107 | <field name="type">tree</field> | ||
2185 | 108 | <field name="arch" type="xml"> | ||
2186 | 109 | <tree string="Discount" editable="bottom"> | ||
2187 | 110 | <field name="use_discount" select="1"/> | ||
2188 | 111 | <field name="inv_payment_terms" select="1" readonly="1"/> | ||
2189 | 112 | <field name="discount_window_date" select="1"/> | ||
2190 | 113 | <field name="proposed_discount" select="1"/> | ||
2191 | 114 | <field name="discount_amount" select="1"/> | ||
2192 | 115 | <field name="gl_account" select="1"/> | ||
2193 | 116 | </tree> | ||
2194 | 117 | </field> | ||
2195 | 118 | </record> | ||
2196 | 119 | <!-- credit --> | ||
2197 | 120 | |||
2198 | 121 | <record model="ir.ui.view" id="view_account_wizard_credit_form"> | ||
2199 | 122 | <field name="name">account.wizard.credit.form</field> | ||
2200 | 123 | <field name="model">account.wizard.credit</field> | ||
2201 | 124 | <field name="type">form</field> | ||
2202 | 125 | <field name="arch" type="xml"> | ||
2203 | 126 | <form string="Credits"> | ||
2204 | 127 | <field name="use_credit" select="1"/> | ||
2205 | 128 | <field name="inv_credit" select="1" readonly="1"/> | ||
2206 | 129 | <field name="discount_window_date" select="1" readonly="1"/> | ||
2207 | 130 | <field name="proposed_discount" select="1" readonly="1"/> | ||
2208 | 131 | <field name="discount_amount" select="1" /> | ||
2209 | 132 | <field name="credit_bal" select="1" readonly="1"/> | ||
2210 | 133 | <field name="gl_account" select="1" readonly="1"/> | ||
2211 | 134 | </form> | ||
2212 | 135 | </field> | ||
2213 | 136 | </record> | ||
2214 | 137 | |||
2215 | 138 | <record model="ir.ui.view" id="view_account_wizard_credit_tree"> | ||
2216 | 139 | <field name="name">account.wizard.credit.tree</field> | ||
2217 | 140 | <field name="model">account.wizard.credit</field> | ||
2218 | 141 | <field name="type">tree</field> | ||
2219 | 142 | <field name="arch" type="xml"> | ||
2220 | 143 | <tree string="Credits" editable="bottom"> | ||
2221 | 144 | <field name="use_credit" select="1"/> | ||
2222 | 145 | <field name="inv_credit" select="1" readonly="1"/> | ||
2223 | 146 | <field name="discount_window_date" select="1" readonly="1"/> | ||
2224 | 147 | <field name="proposed_discount" select="1" readonly="1"/> | ||
2225 | 148 | <field name="discount_amount" select="1" /> | ||
2226 | 149 | <field name="credit_bal" select="1" readonly="1"/> | ||
2227 | 150 | <field name="gl_account" select="1" readonly="1"/> | ||
2228 | 151 | </tree> | ||
2229 | 152 | </field> | ||
2230 | 153 | </record> | ||
2231 | 154 | |||
2232 | 155 | |||
2233 | 156 | <!-- credit used --> | ||
2234 | 157 | |||
2235 | 158 | <record model="ir.ui.view" id="view_account_wizard_credit_used_form"> | ||
2236 | 159 | <field name="name">account.wizard.credit.used.form</field> | ||
2237 | 160 | <field name="model">account.wizard.credit.used</field> | ||
2238 | 161 | <field name="type">form</field> | ||
2239 | 162 | <field name="arch" type="xml"> | ||
2240 | 163 | <form string="Previously Applied Credit"> | ||
2241 | 164 | <field name="date_used" select="1"/> | ||
2242 | 165 | <field name="inv_credit" select="1"/> | ||
2243 | 166 | <field name="discount_window_date" select="1"/> | ||
2244 | 167 | <field name="proposed_discount" select="1"/> | ||
2245 | 168 | <field name="amt_used" select="1"/> | ||
2246 | 169 | <field name="inv_move" select="1"/> | ||
2247 | 170 | <field name="gl_account" select="1"/> | ||
2248 | 171 | </form> | ||
2249 | 172 | </field> | ||
2250 | 173 | </record> | ||
2251 | 174 | |||
2252 | 175 | <record model="ir.ui.view" id="view_account_wizard_credit_used_tree"> | ||
2253 | 176 | <field name="name">account.wizard.credit.used.tree</field> | ||
2254 | 177 | <field name="model">account.wizard.credit.used</field> | ||
2255 | 178 | <field name="type">tree</field> | ||
2256 | 179 | <field name="arch" type="xml"> | ||
2257 | 180 | <tree string="Previously Applied Credit" editable="bottom"> | ||
2258 | 181 | <field name="date_used" select="1"/> | ||
2259 | 182 | <field name="inv_credit" select="1"/> | ||
2260 | 183 | <field name="discount_window_date" select="1"/> | ||
2261 | 184 | <field name="proposed_discount" select="1"/> | ||
2262 | 185 | <field name="amt_used" select="1"/> | ||
2263 | 186 | <field name="inv_move" select="1"/> | ||
2264 | 187 | <field name="gl_account" select="1"/> | ||
2265 | 188 | </tree> | ||
2266 | 189 | </field> | ||
2267 | 190 | </record> | ||
2268 | 191 | |||
2269 | 192 | <!-- customer payment form modification for discount --> | ||
2270 | 193 | |||
2271 | 194 | |||
2272 | 195 | <record model="ir.ui.view" id="view_vendor_receipt_form_2"> | ||
2273 | 196 | <field name="name">account.voucher.receipt.form.2</field> | ||
2274 | 197 | <field name="model">account.voucher</field> | ||
2275 | 198 | <field name="type">form</field> | ||
2276 | 199 | <field name="inherit_id" ref="account_voucher_credits_us.view_vendor_receipt_form_1"/> | ||
2277 | 200 | <field name="arch" type="xml"> | ||
2278 | 201 | <xpath expr="/form/notebook/page[@string='Payment Information']/field[@name='line_cr_ids']/form/group[@string='Invoice']/group[@color='red']/field[@name='credit_used']" position="before"> | ||
2279 | 202 | <field name="discount_used"/> | ||
2280 | 203 | <newline /> | ||
2281 | 204 | </xpath> | ||
2282 | 205 | <xpath expr="/form/notebook/page[@string='Payment Information']/field/tree/field[@name='credit_used']" position="before"> | ||
2283 | 206 | <field name="discount_used"/> | ||
2284 | 207 | <newline/> | ||
2285 | 208 | </xpath> | ||
2286 | 209 | <xpath expr="/form/notebook/page[@string='Payment Information']/field[@name='line_cr_ids']/form/notebook/page[@string='Credit']" position="before"> | ||
2287 | 210 | <page string="Discount"> | ||
2288 | 211 | <field name="available_discounts" nolabel="1" colspan="4" string="Avilable Discounts" view_mode="tree" /> | ||
2289 | 212 | </page> | ||
2290 | 213 | </xpath> | ||
2291 | 214 | </field> | ||
2292 | 215 | </record> | ||
2293 | 216 | |||
2294 | 217 | |||
2295 | 218 | <record model="ir.ui.view" id="view_account_voucher_line_discount_to_use_tree"> | ||
2296 | 219 | <field name="name">account.voucher.line.discount_to_use.tree</field> | ||
2297 | 220 | <field name="model">account.voucher.line.discount_to_use</field> | ||
2298 | 221 | <field name="type">tree</field> | ||
2299 | 222 | <field name="arch" type="xml"> | ||
2300 | 223 | <tree string="Available Discounts" editable="top"> | ||
2301 | 224 | <field name="use_discount" width="125" on_change="onchage_use_discount(use_discount, proposed_discount)"/> | ||
2302 | 225 | <field name="inv_payment_terms"/> | ||
2303 | 226 | <field name="discount_window_date"/> | ||
2304 | 227 | <field name="proposed_discount"/> | ||
2305 | 228 | <field name="discount_amount" on_change="onchage_discount_amount(proposed_discount, discount_amount)"/> | ||
2306 | 229 | <field name="gl_account"/> | ||
2307 | 230 | </tree> | ||
2308 | 231 | </field> | ||
2309 | 232 | </record> | ||
2310 | 233 | |||
2311 | 234 | <record model="ir.ui.view" id="view_payment_term_form_inherited"> | ||
2312 | 235 | <field name="name">account.payment.term.form.inherited</field> | ||
2313 | 236 | <field name="model">account.payment.term</field> | ||
2314 | 237 | <field name="inherit_id" ref="account_cash_discount.view_payment_term_form"/> | ||
2315 | 238 | <field name="arch" type="xml"> | ||
2316 | 239 | <separator string="Cash Discount" colspan="4" position="replace"/> | ||
2317 | 240 | </field> | ||
2318 | 241 | </record> | ||
2319 | 242 | <record model="ir.ui.view" id="view_payment_term_form_inherited2"> | ||
2320 | 243 | <field name="name">account.payment.term.form.inherited2</field> | ||
2321 | 244 | <field name="model">account.payment.term</field> | ||
2322 | 245 | <field name="inherit_id" ref="view_payment_term_form_inherited"/> | ||
2323 | 246 | <field name="arch" type="xml"> | ||
2324 | 247 | <field name="cash_discount_ids" colspan="4" position="replace"> | ||
2325 | 248 | <separator string="Cash Discount" colspan="4"/> | ||
2326 | 249 | <field name="cash_discount_ids" colspan="4" nolabel="1"/> | ||
2327 | 250 | </field> | ||
2328 | 251 | </field> | ||
2329 | 252 | </record> | ||
2330 | 253 | |||
2331 | 254 | |||
2332 | 255 | </data> | ||
2333 | 256 | </openerp> | ||
2334 | 0 | 257 | ||
2335 | === added directory 'account_cash_discount_us/account_cash_discount_us/i18n' | |||
2336 | === added file 'account_cash_discount_us/account_cash_discount_us/i18n/account_cash_discount.pot' | |||
2337 | --- account_cash_discount_us/account_cash_discount_us/i18n/account_cash_discount.pot 1970-01-01 00:00:00 +0000 | |||
2338 | +++ account_cash_discount_us/account_cash_discount_us/i18n/account_cash_discount.pot 2011-10-06 15:23:28 +0000 | |||
2339 | @@ -0,0 +1,85 @@ | |||
2340 | 1 | # Translation of OpenERP Server. | ||
2341 | 2 | # This file contains the translation of the following modules: | ||
2342 | 3 | # * account_cash_discount | ||
2343 | 4 | # | ||
2344 | 5 | msgid "" | ||
2345 | 6 | msgstr "" | ||
2346 | 7 | "Project-Id-Version: OpenERP Server 5.0.6\n" | ||
2347 | 8 | "Report-Msgid-Bugs-To: support@openerp.com\n" | ||
2348 | 9 | "POT-Creation-Date: 2009-11-24 13:09:22+0000\n" | ||
2349 | 10 | "PO-Revision-Date: 2009-11-24 13:09:22+0000\n" | ||
2350 | 11 | "Last-Translator: <>\n" | ||
2351 | 12 | "Language-Team: \n" | ||
2352 | 13 | "MIME-Version: 1.0\n" | ||
2353 | 14 | "Content-Type: text/plain; charset=UTF-8\n" | ||
2354 | 15 | "Content-Transfer-Encoding: \n" | ||
2355 | 16 | "Plural-Forms: \n" | ||
2356 | 17 | |||
2357 | 18 | #. module: account_cash_discount | ||
2358 | 19 | #: constraint:ir.ui.view:0 | ||
2359 | 20 | msgid "Invalid XML for View Architecture!" | ||
2360 | 21 | msgstr "" | ||
2361 | 22 | |||
2362 | 23 | #. module: account_cash_discount | ||
2363 | 24 | #: constraint:ir.model:0 | ||
2364 | 25 | msgid "The Object name must start with x_ and not contain any special character !" | ||
2365 | 26 | msgstr "" | ||
2366 | 27 | |||
2367 | 28 | #. module: account_cash_discount | ||
2368 | 29 | #: field:account.cash.discount,name:0 | ||
2369 | 30 | msgid "Name" | ||
2370 | 31 | msgstr "" | ||
2371 | 32 | |||
2372 | 33 | #. module: account_cash_discount | ||
2373 | 34 | #: field:account.cash.discount,delay:0 | ||
2374 | 35 | msgid "Number of Days" | ||
2375 | 36 | msgstr "" | ||
2376 | 37 | |||
2377 | 38 | #. module: account_cash_discount | ||
2378 | 39 | #: field:account.cash.discount,discount:0 | ||
2379 | 40 | msgid "Discount (%)" | ||
2380 | 41 | msgstr "" | ||
2381 | 42 | |||
2382 | 43 | #. module: account_cash_discount | ||
2383 | 44 | #: field:account.cash.discount,credit_account_id:0 | ||
2384 | 45 | msgid "Credit Account" | ||
2385 | 46 | msgstr "" | ||
2386 | 47 | |||
2387 | 48 | #. module: account_cash_discount | ||
2388 | 49 | #: field:account.cash.discount,debit_account_id:0 | ||
2389 | 50 | msgid "Debit Account" | ||
2390 | 51 | msgstr "" | ||
2391 | 52 | |||
2392 | 53 | #. module: account_cash_discount | ||
2393 | 54 | #: model:ir.module.module,description:account_cash_discount.module_meta_information | ||
2394 | 55 | msgid "\n" | ||
2395 | 56 | " This module adds cash discounts on payment terms. Cash discounts\n" | ||
2396 | 57 | " for a payment term can be configured with:\n" | ||
2397 | 58 | " * A number of days,\n" | ||
2398 | 59 | " * A discount (%),\n" | ||
2399 | 60 | " * A debit and a credit account\n" | ||
2400 | 61 | " " | ||
2401 | 62 | msgstr "" | ||
2402 | 63 | |||
2403 | 64 | #. module: account_cash_discount | ||
2404 | 65 | #: model:ir.module.module,shortdesc:account_cash_discount.module_meta_information | ||
2405 | 66 | msgid "Payement Term with Cash Discount" | ||
2406 | 67 | msgstr "" | ||
2407 | 68 | |||
2408 | 69 | #. module: account_cash_discount | ||
2409 | 70 | #: view:account.cash.discount:0 | ||
2410 | 71 | #: view:account.payment.term:0 | ||
2411 | 72 | #: model:ir.model,name:account_cash_discount.model_account_cash_discount | ||
2412 | 73 | msgid "Cash Discount" | ||
2413 | 74 | msgstr "" | ||
2414 | 75 | |||
2415 | 76 | #. module: account_cash_discount | ||
2416 | 77 | #: field:account.cash.discount,payment_id:0 | ||
2417 | 78 | msgid "Associated Payment Term" | ||
2418 | 79 | msgstr "" | ||
2419 | 80 | |||
2420 | 81 | #. module: account_cash_discount | ||
2421 | 82 | #: field:account.payment.term,cash_discount_ids:0 | ||
2422 | 83 | msgid "Cash Discounts" | ||
2423 | 84 | msgstr "" | ||
2424 | 85 | |||
2425 | 0 | 86 | ||
2426 | === added file 'account_cash_discount_us/account_cash_discount_us/i18n/fr_BE.po' | |||
2427 | --- account_cash_discount_us/account_cash_discount_us/i18n/fr_BE.po 1970-01-01 00:00:00 +0000 | |||
2428 | +++ account_cash_discount_us/account_cash_discount_us/i18n/fr_BE.po 2011-10-06 15:23:28 +0000 | |||
2429 | @@ -0,0 +1,85 @@ | |||
2430 | 1 | # Translation of OpenERP Server. | ||
2431 | 2 | # This file contains the translation of the following modules: | ||
2432 | 3 | # * account_cash_discount | ||
2433 | 4 | # | ||
2434 | 5 | msgid "" | ||
2435 | 6 | msgstr "" | ||
2436 | 7 | "Project-Id-Version: OpenERP Server 5.0.6\n" | ||
2437 | 8 | "Report-Msgid-Bugs-To: support@openerp.com\n" | ||
2438 | 9 | "POT-Creation-Date: 2009-11-24 13:09:22+0000\n" | ||
2439 | 10 | "PO-Revision-Date: 2009-11-24 13:09:22+0000\n" | ||
2440 | 11 | "Last-Translator: <>\n" | ||
2441 | 12 | "Language-Team: \n" | ||
2442 | 13 | "MIME-Version: 1.0\n" | ||
2443 | 14 | "Content-Type: text/plain; charset=UTF-8\n" | ||
2444 | 15 | "Content-Transfer-Encoding: \n" | ||
2445 | 16 | "Plural-Forms: \n" | ||
2446 | 17 | |||
2447 | 18 | #. module: account_cash_discount | ||
2448 | 19 | #: constraint:ir.ui.view:0 | ||
2449 | 20 | msgid "Invalid XML for View Architecture!" | ||
2450 | 21 | msgstr "" | ||
2451 | 22 | |||
2452 | 23 | #. module: account_cash_discount | ||
2453 | 24 | #: constraint:ir.model:0 | ||
2454 | 25 | msgid "The Object name must start with x_ and not contain any special character !" | ||
2455 | 26 | msgstr "" | ||
2456 | 27 | |||
2457 | 28 | #. module: account_cash_discount | ||
2458 | 29 | #: field:account.cash.discount,name:0 | ||
2459 | 30 | msgid "Name" | ||
2460 | 31 | msgstr "" | ||
2461 | 32 | |||
2462 | 33 | #. module: account_cash_discount | ||
2463 | 34 | #: field:account.cash.discount,delay:0 | ||
2464 | 35 | msgid "Number of Days" | ||
2465 | 36 | msgstr "" | ||
2466 | 37 | |||
2467 | 38 | #. module: account_cash_discount | ||
2468 | 39 | #: field:account.cash.discount,discount:0 | ||
2469 | 40 | msgid "Discount (%)" | ||
2470 | 41 | msgstr "" | ||
2471 | 42 | |||
2472 | 43 | #. module: account_cash_discount | ||
2473 | 44 | #: field:account.cash.discount,credit_account_id:0 | ||
2474 | 45 | msgid "Credit Account" | ||
2475 | 46 | msgstr "" | ||
2476 | 47 | |||
2477 | 48 | #. module: account_cash_discount | ||
2478 | 49 | #: field:account.cash.discount,debit_account_id:0 | ||
2479 | 50 | msgid "Debit Account" | ||
2480 | 51 | msgstr "" | ||
2481 | 52 | |||
2482 | 53 | #. module: account_cash_discount | ||
2483 | 54 | #: model:ir.module.module,description:account_cash_discount.module_meta_information | ||
2484 | 55 | msgid "\n" | ||
2485 | 56 | " This module adds cash discounts on payment terms. Cash discounts\n" | ||
2486 | 57 | " for a payment term can be configured with:\n" | ||
2487 | 58 | " * A number of days,\n" | ||
2488 | 59 | " * A discount (%),\n" | ||
2489 | 60 | " * A debit and a credit account\n" | ||
2490 | 61 | " " | ||
2491 | 62 | msgstr "" | ||
2492 | 63 | |||
2493 | 64 | #. module: account_cash_discount | ||
2494 | 65 | #: model:ir.module.module,shortdesc:account_cash_discount.module_meta_information | ||
2495 | 66 | msgid "Payement Term with Cash Discount" | ||
2496 | 67 | msgstr "" | ||
2497 | 68 | |||
2498 | 69 | #. module: account_cash_discount | ||
2499 | 70 | #: view:account.cash.discount:0 | ||
2500 | 71 | #: view:account.payment.term:0 | ||
2501 | 72 | #: model:ir.model,name:account_cash_discount.model_account_cash_discount | ||
2502 | 73 | msgid "Cash Discount" | ||
2503 | 74 | msgstr "" | ||
2504 | 75 | |||
2505 | 76 | #. module: account_cash_discount | ||
2506 | 77 | #: field:account.cash.discount,payment_id:0 | ||
2507 | 78 | msgid "Associated Payment Term" | ||
2508 | 79 | msgstr "" | ||
2509 | 80 | |||
2510 | 81 | #. module: account_cash_discount | ||
2511 | 82 | #: field:account.payment.term,cash_discount_ids:0 | ||
2512 | 83 | msgid "Cash Discounts" | ||
2513 | 84 | msgstr "" | ||
2514 | 85 | |||
2515 | 0 | 86 | ||
2516 | === added file 'account_cash_discount_us/account_cash_discount_us/product_view.xml' | |||
2517 | --- account_cash_discount_us/account_cash_discount_us/product_view.xml 1970-01-01 00:00:00 +0000 | |||
2518 | +++ account_cash_discount_us/account_cash_discount_us/product_view.xml 2011-10-06 15:23:28 +0000 | |||
2519 | @@ -0,0 +1,19 @@ | |||
2520 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
2521 | 2 | <openerp> | ||
2522 | 3 | <data> | ||
2523 | 4 | <record id="product_normal_form_view" model="ir.ui.view"> | ||
2524 | 5 | <field name="name">product.normal.form.inherit2</field> | ||
2525 | 6 | <field name="model">product.product</field> | ||
2526 | 7 | <field name="type">form</field> | ||
2527 | 8 | <field name="inherit_id" ref="account.product_normal_form_view"/> | ||
2528 | 9 | <field name="arch" type="xml"> | ||
2529 | 10 | <xpath expr="//field[@name='property_account_expense']" position="after"> | ||
2530 | 11 | <newline/> | ||
2531 | 12 | <field name="sales_discount_account" attrs="{'readonly':[('sale_ok','=',0)]}"/> | ||
2532 | 13 | <field name="purchase_discount_account" attrs="{'readonly':[('purchase_ok','=',0)]}"/> | ||
2533 | 14 | </xpath> | ||
2534 | 15 | </field> | ||
2535 | 16 | </record> | ||
2536 | 17 | </data> | ||
2537 | 18 | </openerp> | ||
2538 | 19 | |||
2539 | 0 | 20 | ||
2540 | === added directory 'account_cash_discount_us/account_cash_discount_us/security' | |||
2541 | === added file 'account_cash_discount_us/account_cash_discount_us/security/ir.model.access.csv' | |||
2542 | --- account_cash_discount_us/account_cash_discount_us/security/ir.model.access.csv 1970-01-01 00:00:00 +0000 | |||
2543 | +++ account_cash_discount_us/account_cash_discount_us/security/ir.model.access.csv 2011-10-06 15:23:28 +0000 | |||
2544 | @@ -0,0 +1,7 @@ | |||
2545 | 1 | "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" | ||
2546 | 2 | "access_account_invoice_pay_writeoff","account.invoice.pay.writeoff","account_cash_discount_us.model_account_invoice_pay_writeoff","account.group_account_user",1,0,0,0 | ||
2547 | 3 | "access_account_invoice_pay_writeoff_manager","account.invoice.pay.writeoff","account_cash_discount_us.model_account_invoice_pay_writeoff","account.group_account_manager",1,1,1,1 | ||
2548 | 4 | "access_account_invoice_pay","account.invoice.pay","account_cash_discount_us.model_account_invoice_pay","account.group_account_user",1,0,0,0 | ||
2549 | 5 | "access_account_invoice_pay_manager","account.invoice.pay","account_cash_discount_us.model_account_invoice_pay","account.group_account_manager",1,1,1,1 | ||
2550 | 6 | "access_account_voucher_line_discount_to_use","account.voucher.line.discount_to_usey","account_cash_discount_us.model_account_voucher_line_discount_to_use","account.group_account_user",1,0,0,0 | ||
2551 | 7 | "access_account_voucher_line_discount_to_use_manager","account.voucher.line.discount_to_use","account_cash_discount_us.model_account_voucher_line_discount_to_use","account.group_account_manager",1,1,1,1 | ||
2552 | 0 | \ No newline at end of file | 8 | \ No newline at end of file |
2553 | 1 | 9 | ||
2554 | === added directory 'account_cash_discount_us/account_cash_discount_us/wizard' | |||
2555 | === added file 'account_cash_discount_us/account_cash_discount_view.xml' | |||
2556 | --- account_cash_discount_us/account_cash_discount_view.xml 1970-01-01 00:00:00 +0000 | |||
2557 | +++ account_cash_discount_us/account_cash_discount_view.xml 2011-10-06 15:23:28 +0000 | |||
2558 | @@ -0,0 +1,329 @@ | |||
2559 | 1 | <?xml version="1.0"?> | ||
2560 | 2 | <openerp> | ||
2561 | 3 | <data> | ||
2562 | 4 | |||
2563 | 5 | <!-- cash discount --> | ||
2564 | 6 | |||
2565 | 7 | <record id="invoice_supplier_form_jdc" model="ir.ui.view"> | ||
2566 | 8 | <field name="name">account.invoice.supplier.form.jdc</field> | ||
2567 | 9 | <field name="model">account.invoice</field> | ||
2568 | 10 | <field name="type">form</field> | ||
2569 | 11 | <field name="priority">2</field> | ||
2570 | 12 | <field name="inherit_id" ref="account.invoice_supplier_form"/> | ||
2571 | 13 | <field name="arch" type="xml"> | ||
2572 | 14 | <xpath expr="/form/notebook/page/field[@name='check_total']" position="after"> | ||
2573 | 15 | <field name="date_discount"/> | ||
2574 | 16 | <field name="amount_discounted"/> | ||
2575 | 17 | </xpath> | ||
2576 | 18 | </field> | ||
2577 | 19 | </record> | ||
2578 | 20 | <record id="invoice_form_jdc1" model="ir.ui.view"> | ||
2579 | 21 | <field name="name">account.invoice.form.jdc1</field> | ||
2580 | 22 | <field name="model">account.invoice</field> | ||
2581 | 23 | <field name="type">form</field> | ||
2582 | 24 | <field name="inherit_id" ref="account.invoice_form"/> | ||
2583 | 25 | <field name="arch" type="xml"> | ||
2584 | 26 | <xpath expr="/form/notebook/page[@string='Invoice']/field[@name='invoice_line']" position="before"> | ||
2585 | 27 | <group colspan="2" col="4"> | ||
2586 | 28 | <field name="date_discount"/> | ||
2587 | 29 | <field name="amount_discounted"/> | ||
2588 | 30 | </group> | ||
2589 | 31 | </xpath> | ||
2590 | 32 | </field> | ||
2591 | 33 | </record> | ||
2592 | 34 | |||
2593 | 35 | |||
2594 | 36 | <!-- | ||
2595 | 37 | Invoice Line | ||
2596 | 38 | --> | ||
2597 | 39 | <record id="view_invoice_line_form_discount" model="ir.ui.view"> | ||
2598 | 40 | <field name="name">account.invoice.line.form.discount</field> | ||
2599 | 41 | <field name="model">account.invoice.line</field> | ||
2600 | 42 | <field name="inherit_id" ref="account.view_invoice_line_form"/> | ||
2601 | 43 | <field name="type">form</field> | ||
2602 | 44 | <field name="arch" type="xml"> | ||
2603 | 45 | <xpath expr="/form/notebook/page/field[@name='discount']" position="after"> | ||
2604 | 46 | <field name="cash_discount"/> | ||
2605 | 47 | </xpath> | ||
2606 | 48 | </field> | ||
2607 | 49 | </record> | ||
2608 | 50 | |||
2609 | 51 | <!-- | ||
2610 | 52 | Products | ||
2611 | 53 | --> | ||
2612 | 54 | <record id="product_normal_form_view_discount" model="ir.ui.view"> | ||
2613 | 55 | <field name="name">product.normal.form.discount</field> | ||
2614 | 56 | <field name="model">product.product</field> | ||
2615 | 57 | <field name="type">form</field> | ||
2616 | 58 | <field eval="7" name="priority"/> | ||
2617 | 59 | <field name="inherit_id" ref="product.product_normal_form_view"/> | ||
2618 | 60 | <field name="arch" type="xml"> | ||
2619 | 61 | <xpath expr="/form/notebook/page[@string='Suppliers']/field[@name='seller_ids']" position="after"> | ||
2620 | 62 | <field name="cash_discount"/> | ||
2621 | 63 | </xpath> | ||
2622 | 64 | </field> | ||
2623 | 65 | </record> | ||
2624 | 66 | |||
2625 | 67 | <!-- | ||
2626 | 68 | Company | ||
2627 | 69 | --> | ||
2628 | 70 | <record id="view_company_form_jdc2" model="ir.ui.view"> | ||
2629 | 71 | <field name="name">res.company.form.jdc2</field> | ||
2630 | 72 | <field name="model">res.company</field> | ||
2631 | 73 | <field name="type">form</field> | ||
2632 | 74 | <field name="inherit_id" ref="account_voucher_credits_us.view_company_form_jdc3"/> | ||
2633 | 75 | <field name="priority" eval="1"/> | ||
2634 | 76 | <field name="arch" type="xml"> | ||
2635 | 77 | <xpath expr="/form/notebook/page[@string='Accounting']/field[@name='writeoff_account']" position="before"> | ||
2636 | 78 | <field name="sales_discount_account" colspan="2" /> | ||
2637 | 79 | <field name="purchase_discount_account" colspan="2" /> | ||
2638 | 80 | <field name="sales_discount_journal" colspan="2"/> | ||
2639 | 81 | <field name="purchase_discount_journal" colspan="2"/> | ||
2640 | 82 | </xpath> | ||
2641 | 83 | </field> | ||
2642 | 84 | </record> | ||
2643 | 85 | |||
2644 | 86 | <!-- Discount --> | ||
2645 | 87 | |||
2646 | 88 | <record model="ir.ui.view" id="view_account_wizard_discount_form"> | ||
2647 | 89 | <field name="name">account.wizard.discount.form</field> | ||
2648 | 90 | <field name="model">account.wizard.discount</field> | ||
2649 | 91 | <field name="type">form</field> | ||
2650 | 92 | <field name="arch" type="xml"> | ||
2651 | 93 | <form string="Discount"> | ||
2652 | 94 | <field name="use_discount" select="1"/> | ||
2653 | 95 | <field name="inv_payment_terms" select="1" readonly="1"/> | ||
2654 | 96 | <field name="discount_window_date" select="1"/> | ||
2655 | 97 | <field name="proposed_discount" select="1"/> | ||
2656 | 98 | <field name="discount_amount" select="1"/> | ||
2657 | 99 | <field name="gl_account" select="1"/> | ||
2658 | 100 | </form> | ||
2659 | 101 | </field> | ||
2660 | 102 | </record> | ||
2661 | 103 | |||
2662 | 104 | <record model="ir.ui.view" id="view_account_wizard_discount_tree"> | ||
2663 | 105 | <field name="name">account.wizard.discount.tree</field> | ||
2664 | 106 | <field name="model">account.wizard.discount</field> | ||
2665 | 107 | <field name="type">tree</field> | ||
2666 | 108 | <field name="arch" type="xml"> | ||
2667 | 109 | <tree string="Discount" editable="bottom"> | ||
2668 | 110 | <field name="use_discount" select="1"/> | ||
2669 | 111 | <field name="inv_payment_terms" select="1" readonly="1"/> | ||
2670 | 112 | <field name="discount_window_date" select="1"/> | ||
2671 | 113 | <field name="proposed_discount" select="1"/> | ||
2672 | 114 | <field name="discount_amount" select="1"/> | ||
2673 | 115 | <field name="gl_account" select="1"/> | ||
2674 | 116 | </tree> | ||
2675 | 117 | </field> | ||
2676 | 118 | </record> | ||
2677 | 119 | <!-- credit --> | ||
2678 | 120 | |||
2679 | 121 | <record model="ir.ui.view" id="view_account_wizard_credit_form"> | ||
2680 | 122 | <field name="name">account.wizard.credit.form</field> | ||
2681 | 123 | <field name="model">account.wizard.credit</field> | ||
2682 | 124 | <field name="type">form</field> | ||
2683 | 125 | <field name="arch" type="xml"> | ||
2684 | 126 | <form string="Credits"> | ||
2685 | 127 | <field name="use_credit" select="1"/> | ||
2686 | 128 | <field name="inv_credit" select="1" readonly="1"/> | ||
2687 | 129 | <field name="discount_window_date" select="1" readonly="1"/> | ||
2688 | 130 | <field name="proposed_discount" select="1" readonly="1"/> | ||
2689 | 131 | <field name="discount_amount" select="1" /> | ||
2690 | 132 | <field name="credit_bal" select="1" readonly="1"/> | ||
2691 | 133 | <field name="gl_account" select="1" readonly="1"/> | ||
2692 | 134 | </form> | ||
2693 | 135 | </field> | ||
2694 | 136 | </record> | ||
2695 | 137 | |||
2696 | 138 | <record model="ir.ui.view" id="view_account_wizard_credit_tree"> | ||
2697 | 139 | <field name="name">account.wizard.credit.tree</field> | ||
2698 | 140 | <field name="model">account.wizard.credit</field> | ||
2699 | 141 | <field name="type">tree</field> | ||
2700 | 142 | <field name="arch" type="xml"> | ||
2701 | 143 | <tree string="Credits" editable="bottom"> | ||
2702 | 144 | <field name="use_credit" select="1"/> | ||
2703 | 145 | <field name="inv_credit" select="1" readonly="1"/> | ||
2704 | 146 | <field name="discount_window_date" select="1" readonly="1"/> | ||
2705 | 147 | <field name="proposed_discount" select="1" readonly="1"/> | ||
2706 | 148 | <field name="discount_amount" select="1" /> | ||
2707 | 149 | <field name="credit_bal" select="1" readonly="1"/> | ||
2708 | 150 | <field name="gl_account" select="1" readonly="1"/> | ||
2709 | 151 | </tree> | ||
2710 | 152 | </field> | ||
2711 | 153 | </record> | ||
2712 | 154 | |||
2713 | 155 | |||
2714 | 156 | <!-- credit used --> | ||
2715 | 157 | |||
2716 | 158 | <record model="ir.ui.view" id="view_account_wizard_credit_used_form"> | ||
2717 | 159 | <field name="name">account.wizard.credit.used.form</field> | ||
2718 | 160 | <field name="model">account.wizard.credit.used</field> | ||
2719 | 161 | <field name="type">form</field> | ||
2720 | 162 | <field name="arch" type="xml"> | ||
2721 | 163 | <form string="Previously Applied Credit"> | ||
2722 | 164 | <field name="date_used" select="1"/> | ||
2723 | 165 | <field name="inv_credit" select="1"/> | ||
2724 | 166 | <field name="discount_window_date" select="1"/> | ||
2725 | 167 | <field name="proposed_discount" select="1"/> | ||
2726 | 168 | <field name="amt_used" select="1"/> | ||
2727 | 169 | <field name="inv_move" select="1"/> | ||
2728 | 170 | <field name="gl_account" select="1"/> | ||
2729 | 171 | </form> | ||
2730 | 172 | </field> | ||
2731 | 173 | </record> | ||
2732 | 174 | |||
2733 | 175 | <record model="ir.ui.view" id="view_account_wizard_credit_used_tree"> | ||
2734 | 176 | <field name="name">account.wizard.credit.used.tree</field> | ||
2735 | 177 | <field name="model">account.wizard.credit.used</field> | ||
2736 | 178 | <field name="type">tree</field> | ||
2737 | 179 | <field name="arch" type="xml"> | ||
2738 | 180 | <tree string="Previously Applied Credit" editable="bottom"> | ||
2739 | 181 | <field name="date_used" select="1"/> | ||
2740 | 182 | <field name="inv_credit" select="1"/> | ||
2741 | 183 | <field name="discount_window_date" select="1"/> | ||
2742 | 184 | <field name="proposed_discount" select="1"/> | ||
2743 | 185 | <field name="amt_used" select="1"/> | ||
2744 | 186 | <field name="inv_move" select="1"/> | ||
2745 | 187 | <field name="gl_account" select="1"/> | ||
2746 | 188 | </tree> | ||
2747 | 189 | </field> | ||
2748 | 190 | </record> | ||
2749 | 191 | |||
2750 | 192 | <!-- Supplier payment form modification for discount --> | ||
2751 | 193 | <record model="ir.ui.view" id="view_vendor_payment_form_inherit"> | ||
2752 | 194 | <field name="name">account.voucher.payment.form.inherit</field> | ||
2753 | 195 | <field name="model">account.voucher</field> | ||
2754 | 196 | <field name="inherit_id" ref="account_voucher.view_vendor_payment_form"/> | ||
2755 | 197 | <field name="type">form</field> | ||
2756 | 198 | <field name="arch" type="xml"> | ||
2757 | 199 | <xpath expr="/form/group/field[@name='amount']" position="attributes" > | ||
2758 | 200 | <attribute name='on_change'>onchange_amount(amount)</attribute> | ||
2759 | 201 | </xpath> | ||
2760 | 202 | <xpath expr="/form/group[@col='10']/button[@name='cancel_voucher']" position="after"> | ||
2761 | 203 | <button name="calc_supp_diff" string="Calculate" type="object" states="draft" icon="gtk-execute" /> | ||
2762 | 204 | </xpath> | ||
2763 | 205 | <xpath expr="//field[@name='line_dr_ids']" position="replace"> | ||
2764 | 206 | <field name="line_dr_ids" default_get="{'journal_id':journal_id, 'type':type, 'partner_id':partner_id}" colspan="4" nolabel="1" height="140" string="Payment Modification"> | ||
2765 | 207 | <tree string="Invoices and Outstanding Transactions" editable="bottom"> | ||
2766 | 208 | <field name="move_line_id" context="{'journal_id':parent.journal_id, 'partner_id':parent.partner_id}" | ||
2767 | 209 | on_change="onchange_move_line_id(move_line_id)" | ||
2768 | 210 | domain="[('account_id.type','in',('receivable','payable')), ('reconcile_id','=', False), ('partner_id','=',parent.partner_id)]" | ||
2769 | 211 | /> | ||
2770 | 212 | <field name="date_original" readonly="1"/> | ||
2771 | 213 | <field name="date_due" readonly="1"/> | ||
2772 | 214 | <field name="amount_original" readonly="1"/> | ||
2773 | 215 | <field name="amount_unreconciled" sum="Open Balance" readonly="1"/> | ||
2774 | 216 | <field name="pay" on_change="onchange_supp_pay(amount, pay, amount_unreconciled, parent.line_cr_ids, parent.amount, credit_used, discount_used, writeoff_amount)"/> | ||
2775 | 217 | <field name="amount" sum="Payment"/> | ||
2776 | 218 | <field name="discount" /> | ||
2777 | 219 | <field name="supp_amount_difference"/> | ||
2778 | 220 | |||
2779 | 221 | <field name="credit_used"/> | ||
2780 | 222 | <field name="account_id"/> | ||
2781 | 223 | <field name="discount_used" invisible="1"/> | ||
2782 | 224 | <field name="writeoff_amount" invisible="1"/> | ||
2783 | 225 | </tree> | ||
2784 | 226 | |||
2785 | 227 | <form string="Supplier Invoices and Outstanding transactions" > | ||
2786 | 228 | <field name="move_line_id" context="{'journal_id':parent.journal_id, 'partner_id':parent.partner_id}" | ||
2787 | 229 | on_change="onchange_move_line_id(move_line_id)" | ||
2788 | 230 | domain="[('account_id.type','=','payable'), ('reconcile_id','=', False), ('partner_id','=',parent.partner_id)]" | ||
2789 | 231 | /> | ||
2790 | 232 | <field name="account_id" groups="base.group_extended" domain="[('type','=','payable')]"/> | ||
2791 | 233 | <field name="invoice_id"/> | ||
2792 | 234 | <field name="date_original" readonly="1"/> | ||
2793 | 235 | <field name="date_due" readonly="1"/> | ||
2794 | 236 | <field name="amount_original" readonly="1"/> | ||
2795 | 237 | <field name="amount_unreconciled" sum="Open Balance" readonly="1"/> | ||
2796 | 238 | <field name="amount" sum="Payment"/> | ||
2797 | 239 | <field name="supp_amount_difference"/> | ||
2798 | 240 | <field name="discount_used"/> | ||
2799 | 241 | <notebook tabpos="up" colspan="4" > | ||
2800 | 242 | <page string="Discount"> | ||
2801 | 243 | <field name="available_discounts" nolabel="1" colspan="4" string="Avilable Discounts" view_mode="tree" /> | ||
2802 | 244 | </page> | ||
2803 | 245 | <page string="Other Info" readonly="1"> | ||
2804 | 246 | <field name='partner_id' readonly="1"/> | ||
2805 | 247 | <field name='untax_amount' readonly="1"/> | ||
2806 | 248 | <field name='type' readonly="1"/> | ||
2807 | 249 | <field name='account_analytic_id' readonly="1"/> | ||
2808 | 250 | <field name='company_id' readonly="1"/> | ||
2809 | 251 | <field name='pay' on_change="onchange_pay(amount, pay, amount_unreconciled, parent.line_dr_ids, parent.amount, credit_used, discount_used, writeoff_amount)"/> | ||
2810 | 252 | </page> | ||
2811 | 253 | </notebook> | ||
2812 | 254 | <newline/> | ||
2813 | 255 | <button name="clear_values" icon='gtk-clear' string="Clear" type="object" colspan="1"/> | ||
2814 | 256 | <button name="recalculate_supp_values" icon='gtk-refresh' string="Re-Calculate" type="object" colspan="1"/> | ||
2815 | 257 | </form> | ||
2816 | 258 | </field> | ||
2817 | 259 | </xpath> | ||
2818 | 260 | |||
2819 | 261 | </field> | ||
2820 | 262 | </record> | ||
2821 | 263 | |||
2822 | 264 | |||
2823 | 265 | <!-- customer payment form modification for discount --> | ||
2824 | 266 | |||
2825 | 267 | |||
2826 | 268 | <record model="ir.ui.view" id="view_vendor_receipt_form_2"> | ||
2827 | 269 | <field name="name">account.voucher.receipt.form.2</field> | ||
2828 | 270 | <field name="model">account.voucher</field> | ||
2829 | 271 | <field name="type">form</field> | ||
2830 | 272 | <field name="inherit_id" ref="account_voucher_credits_us.view_vendor_receipt_form_1"/> | ||
2831 | 273 | <field name="arch" type="xml"> | ||
2832 | 274 | <xpath expr="/form/notebook/page[@string='Payment Information']/field[@name='line_cr_ids']/form/group[@string='Invoice']/group[@color='red']/field[@name='credit_used']" position="before"> | ||
2833 | 275 | <field name="discount_used"/> | ||
2834 | 276 | <newline /> | ||
2835 | 277 | </xpath> | ||
2836 | 278 | <xpath expr="/form/notebook/page[@string='Payment Information']/field/tree/field[@name='credit_used']" position="before"> | ||
2837 | 279 | <field name="discount_used"/> | ||
2838 | 280 | <newline/> | ||
2839 | 281 | </xpath> | ||
2840 | 282 | <xpath expr="/form/notebook/page[@string='Payment Information']/field[@name='line_cr_ids']/form/notebook/page[@string='Credit']" position="before"> | ||
2841 | 283 | <page string="Discount"> | ||
2842 | 284 | <field name="available_discounts" nolabel="1" colspan="4" string="Avilable Discounts" view_mode="tree" /> | ||
2843 | 285 | </page> | ||
2844 | 286 | </xpath> | ||
2845 | 287 | </field> | ||
2846 | 288 | </record> | ||
2847 | 289 | |||
2848 | 290 | |||
2849 | 291 | <record model="ir.ui.view" id="view_account_voucher_line_discount_to_use_tree"> | ||
2850 | 292 | <field name="name">account.voucher.line.discount_to_use.tree</field> | ||
2851 | 293 | <field name="model">account.voucher.line.discount_to_use</field> | ||
2852 | 294 | <field name="type">tree</field> | ||
2853 | 295 | <field name="arch" type="xml"> | ||
2854 | 296 | <tree string="Available Discounts" editable="top"> | ||
2855 | 297 | <field name="use_discount" width="125" on_change="onchage_use_discount(use_discount, proposed_discount)"/> | ||
2856 | 298 | <field name="inv_payment_terms"/> | ||
2857 | 299 | <field name="discount_window_date"/> | ||
2858 | 300 | <field name="proposed_discount"/> | ||
2859 | 301 | <field name="discount_amount" on_change="onchage_discount_amount(proposed_discount, discount_amount)"/> | ||
2860 | 302 | <field name="gl_account"/> | ||
2861 | 303 | </tree> | ||
2862 | 304 | </field> | ||
2863 | 305 | </record> | ||
2864 | 306 | |||
2865 | 307 | <record model="ir.ui.view" id="view_payment_term_form_inherited"> | ||
2866 | 308 | <field name="name">account.payment.term.form.inherited</field> | ||
2867 | 309 | <field name="model">account.payment.term</field> | ||
2868 | 310 | <field name="inherit_id" ref="account_cash_discount.view_payment_term_form"/> | ||
2869 | 311 | <field name="arch" type="xml"> | ||
2870 | 312 | <separator string="Cash Discount" colspan="4" position="replace"/> | ||
2871 | 313 | </field> | ||
2872 | 314 | </record> | ||
2873 | 315 | <record model="ir.ui.view" id="view_payment_term_form_inherited2"> | ||
2874 | 316 | <field name="name">account.payment.term.form.inherited2</field> | ||
2875 | 317 | <field name="model">account.payment.term</field> | ||
2876 | 318 | <field name="inherit_id" ref="view_payment_term_form_inherited"/> | ||
2877 | 319 | <field name="arch" type="xml"> | ||
2878 | 320 | <field name="cash_discount_ids" colspan="4" position="replace"> | ||
2879 | 321 | <separator string="Cash Discount" colspan="4"/> | ||
2880 | 322 | <field name="cash_discount_ids" colspan="4" nolabel="1"/> | ||
2881 | 323 | </field> | ||
2882 | 324 | </field> | ||
2883 | 325 | </record> | ||
2884 | 326 | |||
2885 | 327 | |||
2886 | 328 | </data> | ||
2887 | 329 | </openerp> | ||
2888 | 0 | 330 | ||
2889 | === added file 'account_cash_discount_us/amount_to_words.py' | |||
2890 | --- account_cash_discount_us/amount_to_words.py 1970-01-01 00:00:00 +0000 | |||
2891 | +++ account_cash_discount_us/amount_to_words.py 2011-10-06 15:23:28 +0000 | |||
2892 | @@ -0,0 +1,77 @@ | |||
2893 | 1 | |||
2894 | 2 | # can be used for numbers as large as 999 vigintillion | ||
2895 | 3 | # (vigintillion --> 10 to the power 60) | ||
2896 | 4 | # tested with Python24 vegaseat 07dec2006 | ||
2897 | 5 | |||
2898 | 6 | def int2word(n): | ||
2899 | 7 | """ | ||
2900 | 8 | convert an integer number n into a string of English words | ||
2901 | 9 | """ | ||
2902 | 10 | # break the number into groups of 3 digits using slicing | ||
2903 | 11 | # each group representing hundred, thousand, million, billion, ... | ||
2904 | 12 | if not n: | ||
2905 | 13 | return 'Zero ' | ||
2906 | 14 | n3 = [] | ||
2907 | 15 | r1 = "" | ||
2908 | 16 | # create numeric string | ||
2909 | 17 | ns = str(n) | ||
2910 | 18 | for k in range(3, 33, 3): | ||
2911 | 19 | r = ns[-k:] | ||
2912 | 20 | q = len(ns) - k | ||
2913 | 21 | # break if end of ns has been reached | ||
2914 | 22 | if q < -2: | ||
2915 | 23 | break | ||
2916 | 24 | else: | ||
2917 | 25 | if q >= 0: | ||
2918 | 26 | n3.append(int(r[:3])) | ||
2919 | 27 | elif q >= -1: | ||
2920 | 28 | n3.append(int(r[:2])) | ||
2921 | 29 | elif q >= -2: | ||
2922 | 30 | n3.append(int(r[:1])) | ||
2923 | 31 | r1 = r | ||
2924 | 32 | nw = "" | ||
2925 | 33 | for i, x in enumerate(n3): | ||
2926 | 34 | b1 = x % 10 | ||
2927 | 35 | b2 = (x % 100)//10 | ||
2928 | 36 | b3 = (x % 1000)//100 | ||
2929 | 37 | if x == 0: | ||
2930 | 38 | continue # skip | ||
2931 | 39 | else: | ||
2932 | 40 | t = thousands[i] | ||
2933 | 41 | if b2 == 0: | ||
2934 | 42 | nw = ones[b1] + t + nw | ||
2935 | 43 | elif b2 == 1: | ||
2936 | 44 | nw = tens[b1] + t + nw | ||
2937 | 45 | elif b2 > 1: | ||
2938 | 46 | nw = twenties[b2] + ones[b1] + t + nw | ||
2939 | 47 | if b3 > 0: | ||
2940 | 48 | nw = ones[b3] + "hundred " + nw | ||
2941 | 49 | return nw | ||
2942 | 50 | |||
2943 | 51 | ############# globals ################ | ||
2944 | 52 | |||
2945 | 53 | ones = ["", "One ","Two ","Three ","Four ", "Five ", | ||
2946 | 54 | "Six ","Seven ","Eight ","Nine "] | ||
2947 | 55 | |||
2948 | 56 | tens = ["Ten ","Eleven ","Twelve ","Thirteen ", "Fourteen ", | ||
2949 | 57 | "Fifteen ","Sixteen ","Seventeen ","Eighteen ","Nineteen "] | ||
2950 | 58 | |||
2951 | 59 | twenties = ["","","Twenty ","Thirty ","Forty ", | ||
2952 | 60 | "Fifty ","Sixty ","Seventy ","Eighty ","Ninety "] | ||
2953 | 61 | |||
2954 | 62 | thousands = ["","Thousand ","Million ", "Billion ", "Trillion ", | ||
2955 | 63 | "Quadrillion ", "Quintillion ", "Sextillion ", "Septillion ","Octillion ", | ||
2956 | 64 | "Nonillion ", "Decillion ", "Undecillion ", "Duodecillion ", "Tredecillion ", | ||
2957 | 65 | "Quattuordecillion ", "Sexdecillion ", "Septendecillion ", "Octodecillion ", | ||
2958 | 66 | "Novemdecillion ", "Vigintillion "] | ||
2959 | 67 | |||
2960 | 68 | def amount_to_words(num): | ||
2961 | 69 | # select an integer number n for testing or get it from user input | ||
2962 | 70 | res="" | ||
2963 | 71 | if num < 0: | ||
2964 | 72 | res="Negative " | ||
2965 | 73 | num=float(str(num)[1:]) | ||
2966 | 74 | if num==0: return 'Zero' | ||
2967 | 75 | else: | ||
2968 | 76 | n=str(num).split('.') | ||
2969 | 77 | return res+int2word(int(n[0]))+'and '+(len(n)>1 and int(n[1]) and str((num - int(num))*100).split('.')[0] or 'no')+'/100s' | ||
2970 | 0 | 78 | ||
2971 | === added directory 'account_cash_discount_us/i18n' | |||
2972 | === added file 'account_cash_discount_us/i18n/account_cash_discount.pot' | |||
2973 | --- account_cash_discount_us/i18n/account_cash_discount.pot 1970-01-01 00:00:00 +0000 | |||
2974 | +++ account_cash_discount_us/i18n/account_cash_discount.pot 2011-10-06 15:23:28 +0000 | |||
2975 | @@ -0,0 +1,85 @@ | |||
2976 | 1 | # Translation of OpenERP Server. | ||
2977 | 2 | # This file contains the translation of the following modules: | ||
2978 | 3 | # * account_cash_discount | ||
2979 | 4 | # | ||
2980 | 5 | msgid "" | ||
2981 | 6 | msgstr "" | ||
2982 | 7 | "Project-Id-Version: OpenERP Server 5.0.6\n" | ||
2983 | 8 | "Report-Msgid-Bugs-To: support@openerp.com\n" | ||
2984 | 9 | "POT-Creation-Date: 2009-11-24 13:09:22+0000\n" | ||
2985 | 10 | "PO-Revision-Date: 2009-11-24 13:09:22+0000\n" | ||
2986 | 11 | "Last-Translator: <>\n" | ||
2987 | 12 | "Language-Team: \n" | ||
2988 | 13 | "MIME-Version: 1.0\n" | ||
2989 | 14 | "Content-Type: text/plain; charset=UTF-8\n" | ||
2990 | 15 | "Content-Transfer-Encoding: \n" | ||
2991 | 16 | "Plural-Forms: \n" | ||
2992 | 17 | |||
2993 | 18 | #. module: account_cash_discount | ||
2994 | 19 | #: constraint:ir.ui.view:0 | ||
2995 | 20 | msgid "Invalid XML for View Architecture!" | ||
2996 | 21 | msgstr "" | ||
2997 | 22 | |||
2998 | 23 | #. module: account_cash_discount | ||
2999 | 24 | #: constraint:ir.model:0 | ||
3000 | 25 | msgid "The Object name must start with x_ and not contain any special character !" | ||
3001 | 26 | msgstr "" | ||
3002 | 27 | |||
3003 | 28 | #. module: account_cash_discount | ||
3004 | 29 | #: field:account.cash.discount,name:0 | ||
3005 | 30 | msgid "Name" | ||
3006 | 31 | msgstr "" | ||
3007 | 32 | |||
3008 | 33 | #. module: account_cash_discount | ||
3009 | 34 | #: field:account.cash.discount,delay:0 | ||
3010 | 35 | msgid "Number of Days" | ||
3011 | 36 | msgstr "" | ||
3012 | 37 | |||
3013 | 38 | #. module: account_cash_discount | ||
3014 | 39 | #: field:account.cash.discount,discount:0 | ||
3015 | 40 | msgid "Discount (%)" | ||
3016 | 41 | msgstr "" | ||
3017 | 42 | |||
3018 | 43 | #. module: account_cash_discount | ||
3019 | 44 | #: field:account.cash.discount,credit_account_id:0 | ||
3020 | 45 | msgid "Credit Account" | ||
3021 | 46 | msgstr "" | ||
3022 | 47 | |||
3023 | 48 | #. module: account_cash_discount | ||
3024 | 49 | #: field:account.cash.discount,debit_account_id:0 | ||
3025 | 50 | msgid "Debit Account" | ||
3026 | 51 | msgstr "" | ||
3027 | 52 | |||
3028 | 53 | #. module: account_cash_discount | ||
3029 | 54 | #: model:ir.module.module,description:account_cash_discount.module_meta_information | ||
3030 | 55 | msgid "\n" | ||
3031 | 56 | " This module adds cash discounts on payment terms. Cash discounts\n" | ||
3032 | 57 | " for a payment term can be configured with:\n" | ||
3033 | 58 | " * A number of days,\n" | ||
3034 | 59 | " * A discount (%),\n" | ||
3035 | 60 | " * A debit and a credit account\n" | ||
3036 | 61 | " " | ||
3037 | 62 | msgstr "" | ||
3038 | 63 | |||
3039 | 64 | #. module: account_cash_discount | ||
3040 | 65 | #: model:ir.module.module,shortdesc:account_cash_discount.module_meta_information | ||
3041 | 66 | msgid "Payement Term with Cash Discount" | ||
3042 | 67 | msgstr "" | ||
3043 | 68 | |||
3044 | 69 | #. module: account_cash_discount | ||
3045 | 70 | #: view:account.cash.discount:0 | ||
3046 | 71 | #: view:account.payment.term:0 | ||
3047 | 72 | #: model:ir.model,name:account_cash_discount.model_account_cash_discount | ||
3048 | 73 | msgid "Cash Discount" | ||
3049 | 74 | msgstr "" | ||
3050 | 75 | |||
3051 | 76 | #. module: account_cash_discount | ||
3052 | 77 | #: field:account.cash.discount,payment_id:0 | ||
3053 | 78 | msgid "Associated Payment Term" | ||
3054 | 79 | msgstr "" | ||
3055 | 80 | |||
3056 | 81 | #. module: account_cash_discount | ||
3057 | 82 | #: field:account.payment.term,cash_discount_ids:0 | ||
3058 | 83 | msgid "Cash Discounts" | ||
3059 | 84 | msgstr "" | ||
3060 | 85 | |||
3061 | 0 | 86 | ||
3062 | === added file 'account_cash_discount_us/i18n/fr_BE.po' | |||
3063 | --- account_cash_discount_us/i18n/fr_BE.po 1970-01-01 00:00:00 +0000 | |||
3064 | +++ account_cash_discount_us/i18n/fr_BE.po 2011-10-06 15:23:28 +0000 | |||
3065 | @@ -0,0 +1,85 @@ | |||
3066 | 1 | # Translation of OpenERP Server. | ||
3067 | 2 | # This file contains the translation of the following modules: | ||
3068 | 3 | # * account_cash_discount | ||
3069 | 4 | # | ||
3070 | 5 | msgid "" | ||
3071 | 6 | msgstr "" | ||
3072 | 7 | "Project-Id-Version: OpenERP Server 5.0.6\n" | ||
3073 | 8 | "Report-Msgid-Bugs-To: support@openerp.com\n" | ||
3074 | 9 | "POT-Creation-Date: 2009-11-24 13:09:22+0000\n" | ||
3075 | 10 | "PO-Revision-Date: 2009-11-24 13:09:22+0000\n" | ||
3076 | 11 | "Last-Translator: <>\n" | ||
3077 | 12 | "Language-Team: \n" | ||
3078 | 13 | "MIME-Version: 1.0\n" | ||
3079 | 14 | "Content-Type: text/plain; charset=UTF-8\n" | ||
3080 | 15 | "Content-Transfer-Encoding: \n" | ||
3081 | 16 | "Plural-Forms: \n" | ||
3082 | 17 | |||
3083 | 18 | #. module: account_cash_discount | ||
3084 | 19 | #: constraint:ir.ui.view:0 | ||
3085 | 20 | msgid "Invalid XML for View Architecture!" | ||
3086 | 21 | msgstr "" | ||
3087 | 22 | |||
3088 | 23 | #. module: account_cash_discount | ||
3089 | 24 | #: constraint:ir.model:0 | ||
3090 | 25 | msgid "The Object name must start with x_ and not contain any special character !" | ||
3091 | 26 | msgstr "" | ||
3092 | 27 | |||
3093 | 28 | #. module: account_cash_discount | ||
3094 | 29 | #: field:account.cash.discount,name:0 | ||
3095 | 30 | msgid "Name" | ||
3096 | 31 | msgstr "" | ||
3097 | 32 | |||
3098 | 33 | #. module: account_cash_discount | ||
3099 | 34 | #: field:account.cash.discount,delay:0 | ||
3100 | 35 | msgid "Number of Days" | ||
3101 | 36 | msgstr "" | ||
3102 | 37 | |||
3103 | 38 | #. module: account_cash_discount | ||
3104 | 39 | #: field:account.cash.discount,discount:0 | ||
3105 | 40 | msgid "Discount (%)" | ||
3106 | 41 | msgstr "" | ||
3107 | 42 | |||
3108 | 43 | #. module: account_cash_discount | ||
3109 | 44 | #: field:account.cash.discount,credit_account_id:0 | ||
3110 | 45 | msgid "Credit Account" | ||
3111 | 46 | msgstr "" | ||
3112 | 47 | |||
3113 | 48 | #. module: account_cash_discount | ||
3114 | 49 | #: field:account.cash.discount,debit_account_id:0 | ||
3115 | 50 | msgid "Debit Account" | ||
3116 | 51 | msgstr "" | ||
3117 | 52 | |||
3118 | 53 | #. module: account_cash_discount | ||
3119 | 54 | #: model:ir.module.module,description:account_cash_discount.module_meta_information | ||
3120 | 55 | msgid "\n" | ||
3121 | 56 | " This module adds cash discounts on payment terms. Cash discounts\n" | ||
3122 | 57 | " for a payment term can be configured with:\n" | ||
3123 | 58 | " * A number of days,\n" | ||
3124 | 59 | " * A discount (%),\n" | ||
3125 | 60 | " * A debit and a credit account\n" | ||
3126 | 61 | " " | ||
3127 | 62 | msgstr "" | ||
3128 | 63 | |||
3129 | 64 | #. module: account_cash_discount | ||
3130 | 65 | #: model:ir.module.module,shortdesc:account_cash_discount.module_meta_information | ||
3131 | 66 | msgid "Payement Term with Cash Discount" | ||
3132 | 67 | msgstr "" | ||
3133 | 68 | |||
3134 | 69 | #. module: account_cash_discount | ||
3135 | 70 | #: view:account.cash.discount:0 | ||
3136 | 71 | #: view:account.payment.term:0 | ||
3137 | 72 | #: model:ir.model,name:account_cash_discount.model_account_cash_discount | ||
3138 | 73 | msgid "Cash Discount" | ||
3139 | 74 | msgstr "" | ||
3140 | 75 | |||
3141 | 76 | #. module: account_cash_discount | ||
3142 | 77 | #: field:account.cash.discount,payment_id:0 | ||
3143 | 78 | msgid "Associated Payment Term" | ||
3144 | 79 | msgstr "" | ||
3145 | 80 | |||
3146 | 81 | #. module: account_cash_discount | ||
3147 | 82 | #: field:account.payment.term,cash_discount_ids:0 | ||
3148 | 83 | msgid "Cash Discounts" | ||
3149 | 84 | msgstr "" | ||
3150 | 85 | |||
3151 | 0 | 86 | ||
3152 | === added file 'account_cash_discount_us/product_view.xml' | |||
3153 | --- account_cash_discount_us/product_view.xml 1970-01-01 00:00:00 +0000 | |||
3154 | +++ account_cash_discount_us/product_view.xml 2011-10-06 15:23:28 +0000 | |||
3155 | @@ -0,0 +1,19 @@ | |||
3156 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
3157 | 2 | <openerp> | ||
3158 | 3 | <data> | ||
3159 | 4 | <record id="product_normal_form_view" model="ir.ui.view"> | ||
3160 | 5 | <field name="name">product.normal.form.inherit2</field> | ||
3161 | 6 | <field name="model">product.product</field> | ||
3162 | 7 | <field name="type">form</field> | ||
3163 | 8 | <field name="inherit_id" ref="account.product_normal_form_view"/> | ||
3164 | 9 | <field name="arch" type="xml"> | ||
3165 | 10 | <xpath expr="//field[@name='property_account_expense']" position="after"> | ||
3166 | 11 | <newline/> | ||
3167 | 12 | <field name="sales_discount_account" attrs="{'readonly':[('sale_ok','=',0)]}"/> | ||
3168 | 13 | <field name="purchase_discount_account" attrs="{'readonly':[('purchase_ok','=',0)]}"/> | ||
3169 | 14 | </xpath> | ||
3170 | 15 | </field> | ||
3171 | 16 | </record> | ||
3172 | 17 | </data> | ||
3173 | 18 | </openerp> | ||
3174 | 19 | |||
3175 | 0 | 20 | ||
3176 | === added directory 'account_cash_discount_us/security' | |||
3177 | === added file 'account_cash_discount_us/security/ir.model.access.csv' | |||
3178 | --- account_cash_discount_us/security/ir.model.access.csv 1970-01-01 00:00:00 +0000 | |||
3179 | +++ account_cash_discount_us/security/ir.model.access.csv 2011-10-06 15:23:28 +0000 | |||
3180 | @@ -0,0 +1,7 @@ | |||
3181 | 1 | "id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" | ||
3182 | 2 | "access_account_invoice_pay_writeoff","account.invoice.pay.writeoff","account_cash_discount_us.model_account_invoice_pay_writeoff","account.group_account_user",1,0,0,0 | ||
3183 | 3 | "access_account_invoice_pay_writeoff_manager","account.invoice.pay.writeoff","account_cash_discount_us.model_account_invoice_pay_writeoff","account.group_account_manager",1,1,1,1 | ||
3184 | 4 | "access_account_invoice_pay","account.invoice.pay","account_cash_discount_us.model_account_invoice_pay","account.group_account_user",1,0,0,0 | ||
3185 | 5 | "access_account_invoice_pay_manager","account.invoice.pay","account_cash_discount_us.model_account_invoice_pay","account.group_account_manager",1,1,1,1 | ||
3186 | 6 | "access_account_voucher_line_discount_to_use","account.voucher.line.discount_to_usey","account_cash_discount_us.model_account_voucher_line_discount_to_use","account.group_account_user",1,0,0,0 | ||
3187 | 7 | "access_account_voucher_line_discount_to_use_manager","account.voucher.line.discount_to_use","account_cash_discount_us.model_account_voucher_line_discount_to_use","account.group_account_manager",1,1,1,1 | ||
3188 | 0 | \ No newline at end of file | 8 | \ No newline at end of file |