Merge lp:~therp-nl/banking-addons/ba7.0-MIG-payment into lp:banking-addons
- ba7.0-MIG-payment
- Merge into banking-addons-70
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | 174 | ||||
Proposed branch: | lp:~therp-nl/banking-addons/ba7.0-MIG-payment | ||||
Merge into: | lp:banking-addons | ||||
Prerequisite: | lp:~therp-nl/banking-addons/ba7.0-MIG-import | ||||
Diff against target: |
4032 lines (+1174/-1209) 48 files modified
account_banking/account_banking.py (+26/-26) account_banking/account_banking_view.xml (+0/-9) account_banking/banking_import_transaction.py (+84/-85) account_banking/wizard/bank_import.py (+16/-16) account_banking/wizard/bank_import_view.xml (+0/-1) account_banking/wizard/banking_transaction_wizard.py (+40/-66) account_banking/wizard/banking_transaction_wizard.xml (+0/-1) account_banking/wizard/banktools.py (+18/-18) account_banking_nl_clieop/__openerp__.py (+1/-1) account_banking_nl_clieop/account_banking_nl_clieop.py (+7/-8) account_banking_nl_clieop/account_banking_nl_clieop.xml (+0/-2) account_banking_nl_clieop/wizard/export_clieop.py (+42/-48) account_banking_nl_clieop/wizard/export_clieop_view.xml (+0/-1) account_banking_nl_girotel/girotel.py (+14/-2) account_banking_payment/__openerp__.py (+2/-1) account_banking_payment/model/__init__.py (+0/-1) account_banking_payment/model/account_bank_statement_line.py (+0/-40) account_banking_payment/model/account_payment.py (+166/-46) account_banking_payment/model/banking_import_transaction.py (+56/-46) account_banking_payment/model/banking_transaction_wizard.py (+58/-0) account_banking_payment/model/payment_line.py (+91/-129) account_banking_payment/model/payment_mode.py (+21/-0) account_banking_payment/model/payment_order_create.py (+74/-5) account_banking_payment/view/account_payment.xml (+16/-21) account_banking_payment/view/bank_payment_manual.xml (+1/-2) account_banking_payment/view/banking_transaction_wizard.xml (+11/-9) account_banking_payment/view/payment_mode.xml (+43/-0) account_banking_payment/view/payment_mode_type.xml (+1/-16) account_banking_payment/workflow/account_payment.xml (+40/-9) account_banking_uk_hsbc/__openerp__.py (+1/-1) account_direct_debit/__openerp__.py (+4/-5) account_direct_debit/i18n/nl.po (+2/-2) account_direct_debit/migrations/7.0.2/pre-migration.py (+57/-0) account_direct_debit/model/__init__.py (+2/-0) account_direct_debit/model/account_invoice.py (+26/-5) account_direct_debit/model/account_move_line.py (+7/-67) account_direct_debit/model/account_payment.py (+5/-434) account_direct_debit/model/payment_line.py (+152/-0) account_direct_debit/model/payment_order_create.py (+41/-0) account_direct_debit/view/account_invoice.xml (+5/-10) account_direct_debit/view/account_payment.xml (+2/-28) account_direct_debit/workflow/account_payment.xml (+0/-25) account_payment_shortcut/__init__.py (+1/-0) account_payment_shortcut/payment_order.py (+26/-6) bank_statement_instant_voucher/model/account_bank_statement_line.py (+5/-5) bank_statement_instant_voucher/model/account_voucher_instant.py (+10/-10) bank_statement_instant_voucher/view/account_bank_statement_line.xml (+0/-1) bank_statement_instant_voucher/view/account_voucher_instant.xml (+0/-1) |
||||
To merge this branch: | bzr merge lp:~therp-nl/banking-addons/ba7.0-MIG-payment | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Holger Brunn (Therp) | Approve | ||
Review via email: mp+166451@code.launchpad.net |
Commit message
[MRG] Migration of payment modules
Description of the change
- Apply invoice integration of debit orders also to payment orders
- Allow for manual reconciliation of payment and debit orders
- Update payment order workflow so as to allow for unreconciliation
- Consistency in usage of cr and uid variable names
- Adapt to API changes
- Removed obsolete workaround for old bugs in OpenERP server
- Remove unused code paths
For migrations from 6.1, I am still considering how to provide an upgrade path that migrates payment order workflow instances in activity 'sent' to the new 'sent_wait' state.
Holger Brunn (Therp) (hbrunn) wrote : | # |
should I wait with merging this one until you had a look at my points?
Stefan Rijnhart (Opener) (stefan-opener) wrote : | # |
Yes, will do so this week! Thanks for the review.
- 227. By Stefan Rijnhart (Opener)
-
[MGR] HSBC module depends on split off payment part
- 228. By Stefan Rijnhart (Opener)
-
[FIX] Add context to browse calls in account_banking.py
- 229. By Stefan Rijnhart (Opener)
-
[FIX] Improve translatable labels for move and move lines
- 230. By Stefan Rijnhart (Opener)
-
[MRG] Merged with target branch
Stefan Rijnhart (Opener) (stefan-opener) wrote : | # |
Holger, thanks for your comments. I tried to address them in my latest commits or the comments below.
> #550 570, 880 considering how often you use this selection, you should move it to its own field. This also
> simplifies adjusting the selection
I'll leave it for now as I want to refactor it later on to make the selection options more dynamic.
> #1591 check if there are line_ids
As this code path occurs after a match with a bank transaction on amount, an absence of line_ids should not occur as the payment order amount would be zero as would the transaction amount.
> #1784 why can we drop this check? shouldn't it be changed to check for transit_
As per l.1591, implement old style behaviour for legacy payment orders depending on the presence of transit_
The sent state implements the transit move. Making it go into sent_wait allows the reconciliation process to cancel and reconfirm confirmed matches. Before I introduced the latter state and modified the workflow to go from 'done' to 'sent', I could not reconfirm a match on a payment order, because then the workflow would attempt to create the transit move again. I'd think that a manual migration for wkf instances currently in the 'sent' state should be necessary, or they might get stuck at that state.
Preview Diff
1 | === modified file 'account_banking/account_banking.py' |
2 | --- account_banking/account_banking.py 2013-04-29 09:17:46 +0000 |
3 | +++ account_banking/account_banking.py 2013-06-26 21:16:23 +0000 |
4 | @@ -267,7 +267,7 @@ |
5 | } |
6 | _defaults = { |
7 | 'date': fields.date.context_today, |
8 | - 'user_id': lambda self, cursor, uid, context: uid, |
9 | + 'user_id': lambda self, cr, uid, context: uid, |
10 | } |
11 | account_banking_imported_file() |
12 | |
13 | @@ -320,12 +320,12 @@ |
14 | ['journal_id','period_id']), |
15 | ] |
16 | |
17 | - def _get_period(self, cursor, uid, date, context=None): |
18 | + def _get_period(self, cr, uid, date, context=None): |
19 | ''' |
20 | Find matching period for date, not meant for _defaults. |
21 | ''' |
22 | period_obj = self.pool.get('account.period') |
23 | - periods = period_obj.find(cursor, uid, dt=date, context=context) |
24 | + periods = period_obj.find(cr, uid, dt=date, context=context) |
25 | return periods and periods[0] or False |
26 | |
27 | def _prepare_move( |
28 | @@ -398,7 +398,7 @@ |
29 | # Write stored reconcile_id and pay invoices through workflow |
30 | if st_line.reconcile_id: |
31 | move_ids = [move.id for move in st_line.move_ids] |
32 | - torec = account_move_obj.search( |
33 | + torec = account_move_line_obj.search( |
34 | cr, uid, [ |
35 | ('move_id', 'in', move_ids), |
36 | ('account_id', '=', st_line.account_id.id)], |
37 | @@ -450,7 +450,7 @@ |
38 | context = {} |
39 | if not context.get('period_id') and context.get('move_line_ids'): |
40 | return self.pool.get('account.move.line').browse( |
41 | - cr, uid , context.get('move_line_ids'))[0].period_id.id |
42 | + cr, uid , context.get('move_line_ids'), context=context)[0].period_id.id |
43 | return super(account_voucher, self)._get_period(cr, uid, context) |
44 | |
45 | account_voucher() |
46 | @@ -467,12 +467,12 @@ |
47 | _inherit = 'account.bank.statement.line' |
48 | _description = 'Bank Transaction' |
49 | |
50 | - def _get_period(self, cursor, user, context=None): |
51 | + def _get_period(self, cr, uid, context=None): |
52 | date = context.get('date', None) |
53 | - periods = self.pool.get('account.period').find(cursor, user, dt=date) |
54 | + periods = self.pool.get('account.period').find(cr, uid, dt=date) |
55 | return periods and periods[0] or False |
56 | |
57 | - def _get_currency(self, cursor, user, context=None): |
58 | + def _get_currency(self, cr, uid, context=None): |
59 | ''' |
60 | Get the default currency (required to allow other modules to function, |
61 | which assume currency to be a calculated field and thus optional) |
62 | @@ -480,7 +480,7 @@ |
63 | which is inaccessible from within this method. |
64 | ''' |
65 | res_users_obj = self.pool.get('res.users') |
66 | - return res_users_obj.browse(cursor, user, user, |
67 | + return res_users_obj.browse(cr, uid, uid, |
68 | context=context).company_id.currency_id.id |
69 | |
70 | def _get_invoice_id(self, cr, uid, ids, name, args, context=None): |
71 | @@ -605,7 +605,7 @@ |
72 | iban = sepa.IBAN(acc_number) |
73 | return (str(iban), iban.localized_BBAN) |
74 | |
75 | - def create(self, cursor, uid, vals, context=None): |
76 | + def create(self, cr, uid, vals, context=None): |
77 | ''' |
78 | Create dual function IBAN account for SEPA countries |
79 | ''' |
80 | @@ -614,7 +614,7 @@ |
81 | or vals.get('acc_number_domestic', False)) |
82 | vals['acc_number'], vals['acc_number_domestic'] = ( |
83 | self._correct_IBAN(iban)) |
84 | - return self._founder.create(self, cursor, uid, vals, context) |
85 | + return self._founder.create(self, cr, uid, vals, context) |
86 | |
87 | def write(self, cr, uid, ids, vals, context=None): |
88 | ''' |
89 | @@ -637,7 +637,7 @@ |
90 | self._founder.write(self, cr, uid, account['id'], vals, context) |
91 | return True |
92 | |
93 | - def search(self, cursor, uid, args, *rest, **kwargs): |
94 | + def search(self, cr, uid, args, *rest, **kwargs): |
95 | ''' |
96 | Overwrite search, as both acc_number and iban now can be filled, so |
97 | the original base_iban 'search and search again fuzzy' tactic now can |
98 | @@ -698,7 +698,7 @@ |
99 | |
100 | # Original search |
101 | results = super(res_partner_bank, self).search( |
102 | - cursor, uid, newargs, *rest, **kwargs) |
103 | + cr, uid, newargs, *rest, **kwargs) |
104 | return results |
105 | |
106 | def read( |
107 | @@ -721,23 +721,23 @@ |
108 | return records |
109 | return records[0] |
110 | |
111 | - def check_iban(self, cursor, uid, ids): |
112 | + def check_iban(self, cr, uid, ids, context=None): |
113 | ''' |
114 | Check IBAN number |
115 | ''' |
116 | - for bank_acc in self.browse(cursor, uid, ids): |
117 | + for bank_acc in self.browse(cr, uid, ids, context=context): |
118 | if bank_acc.state == 'iban' and bank_acc.acc_number: |
119 | iban = sepa.IBAN(bank_acc.acc_number) |
120 | if not iban.valid: |
121 | return False |
122 | return True |
123 | |
124 | - def get_bban_from_iban(self, cursor, uid, ids, context=None): |
125 | + def get_bban_from_iban(self, cr, uid, ids, context=None): |
126 | ''' |
127 | Return the local bank account number aka BBAN from the IBAN. |
128 | ''' |
129 | res = {} |
130 | - for record in self.browse(cursor, uid, ids, context): |
131 | + for record in self.browse(cr, uid, ids, context): |
132 | if not record.state == 'iban': |
133 | res[record.id] = False |
134 | else: |
135 | @@ -763,7 +763,7 @@ |
136 | ) |
137 | |
138 | def onchange_domestic( |
139 | - self, cursor, uid, ids, acc_number, |
140 | + self, cr, uid, ids, acc_number, |
141 | partner_id, country_id, context=None): |
142 | ''' |
143 | Trigger to find IBAN. When found: |
144 | @@ -785,7 +785,7 @@ |
145 | # which can be overridden by the user. |
146 | # 1. Use provided country_id (manually filled) |
147 | if country_id: |
148 | - country = country_obj.browse(cursor, uid, country_id) |
149 | + country = country_obj.browse(cr, uid, country_id, context=context) |
150 | country_ids = [country_id] |
151 | # 2. Use country_id of found bank accounts |
152 | # This can be usefull when there is no country set in the partners |
153 | @@ -793,7 +793,7 @@ |
154 | # account itself before this method was triggered. |
155 | elif ids and len(ids) == 1: |
156 | partner_bank_obj = self.pool.get('res.partner.bank') |
157 | - partner_bank_id = partner_bank_obj.browse(cursor, uid, ids[0]) |
158 | + partner_bank_id = partner_bank_obj.browse(cr, uid, ids[0], context=context) |
159 | if partner_bank_id.country_id: |
160 | country = partner_bank_id.country_id |
161 | country_ids = [country.id] |
162 | @@ -804,12 +804,12 @@ |
163 | # bank account, hence the additional check. |
164 | elif partner_id: |
165 | partner_obj = self.pool.get('res.partner') |
166 | - country = partner_obj.browse(cursor, uid, partner_id).country |
167 | + country = partner_obj.browse(cr, uid, partner_id, context=context).country |
168 | country_ids = country and [country.id] or [] |
169 | # 4. Without any of the above, take the country from the company of |
170 | # the handling user |
171 | if not country_ids: |
172 | - user = self.pool.get('res.users').browse(cursor, uid, uid) |
173 | + user = self.pool.get('res.users').browse(cr, uid, uid, context=context) |
174 | # Try user companies partner (user no longer has address in 6.1) |
175 | if (user.company_id and |
176 | user.company_id.partner_id and |
177 | @@ -830,7 +830,7 @@ |
178 | # Complete data with online database when available |
179 | if country_ids: |
180 | country = country_obj.browse( |
181 | - cursor, uid, country_ids[0], context=context) |
182 | + cr, uid, country_ids[0], context=context) |
183 | values['country_id'] = country_ids[0] |
184 | if country and country.code in sepa.IBAN.countries: |
185 | try: |
186 | @@ -842,7 +842,7 @@ |
187 | values['acc_number'] = unicode(iban_acc) |
188 | values['state'] = 'iban' |
189 | bank_id, country_id = get_or_create_bank( |
190 | - self.pool, cursor, uid, |
191 | + self.pool, cr, uid, |
192 | info.bic or iban_acc.BIC_searchkey, |
193 | name = info.bank |
194 | ) |
195 | @@ -911,7 +911,7 @@ |
196 | ''' |
197 | _inherit = 'res.bank' |
198 | |
199 | - def onchange_bic(self, cursor, uid, ids, bic, name, context=None): |
200 | + def onchange_bic(self, cr, uid, ids, bic, name, context=None): |
201 | ''' |
202 | Trigger to auto complete other fields. |
203 | ''' |
204 | @@ -924,7 +924,7 @@ |
205 | |
206 | if address and address.country_id: |
207 | country_id = self.pool.get('res.country').search( |
208 | - cursor, uid, [('code','=',address.country_id)] |
209 | + cr, uid, [('code','=',address.country_id)] |
210 | ) |
211 | country_id = country_id and country_id[0] or False |
212 | else: |
213 | |
214 | === modified file 'account_banking/account_banking_view.xml' |
215 | --- account_banking/account_banking_view.xml 2013-05-01 14:25:04 +0000 |
216 | +++ account_banking/account_banking_view.xml 2013-06-26 21:16:23 +0000 |
217 | @@ -36,7 +36,6 @@ |
218 | <record model="ir.ui.view" id="view_banking_account_settings_form"> |
219 | <field name="name">account.banking.account.settings.form</field> |
220 | <field name="model">account.banking.account.settings</field> |
221 | - <field name="type">form</field> |
222 | <field name="arch" type="xml"> |
223 | <form string="Default Import Settings for Bank Account"> |
224 | <field name="company_id" |
225 | @@ -70,7 +69,6 @@ |
226 | <record model="ir.ui.view" id="view_banking_account_settings_tree"> |
227 | <field name="name">account.banking.account.settings.tree</field> |
228 | <field name="model">account.banking.account.settings</field> |
229 | - <field name="type">tree</field> |
230 | <field name="arch" type="xml"> |
231 | <tree string="Default Import Settings for Bank Account"> |
232 | <field name="company_id" /> |
233 | @@ -99,7 +97,6 @@ |
234 | <record model="ir.ui.view" id="view_account_banking_imported_file_form"> |
235 | <field name="name">account.banking.imported.file.form</field> |
236 | <field name="model">account.banking.imported.file</field> |
237 | - <field name="type">form</field> |
238 | <field name="arch" type="xml"> |
239 | <form string="Imported Bank Statements"> |
240 | <notebook colspan="4"> |
241 | @@ -124,7 +121,6 @@ |
242 | <record model="ir.ui.view" id="view_account_banking_imported_file_tree"> |
243 | <field name="name">account.banking.imported.file.tree</field> |
244 | <field name="model">account.banking.imported.file</field> |
245 | - <field name="type">tree</field> |
246 | <field name="arch" type="xml"> |
247 | <tree string="Imported Bank Statements Files" colors="red:state=='error';blue:state=='unfinished'"> |
248 | <field name="company_id" /> |
249 | @@ -182,7 +178,6 @@ |
250 | <field name="name">account.bank.statement.tree.banking</field> |
251 | <field name="inherit_id" ref="account.view_bank_statement_tree" /> |
252 | <field name="model">account.bank.statement</field> |
253 | - <field name="type">tree</field> |
254 | <field name="arch" type="xml"> |
255 | <!-- Remove period from bank statement --> |
256 | <field name="period_id" position="replace"> |
257 | @@ -197,7 +192,6 @@ |
258 | <field name="inherit_id" ref="account.view_bank_statement_form" /> |
259 | <field name="model">account.bank.statement</field> |
260 | <field name="sequence" eval="60"/> |
261 | - <field name="type">form</field> |
262 | <field name="arch" type="xml"> |
263 | <data> |
264 | <page string="Transactions" position="after"> |
265 | @@ -292,7 +286,6 @@ |
266 | <field name="name">res.partner.bank.form.banking-2</field> |
267 | <field name="model">res.partner.bank</field> |
268 | <field name="inherit_id" ref="base.view_partner_bank_form"/> |
269 | - <field name="type">form</field> |
270 | <field name="priority" eval="24"/> |
271 | <field name="arch" type="xml"> |
272 | <data> |
273 | @@ -311,7 +304,6 @@ |
274 | <field name="name">res.bank.form.banking-1</field> |
275 | <field name="model">res.bank</field> |
276 | <field name="inherit_id" ref="base.view_res_bank_form"/> |
277 | - <field name="type">form</field> |
278 | <field name="arch" type="xml"> |
279 | <field name="bic" position="replace"> |
280 | <field name="bic" on_change="onchange_bic(bic, name)"/> |
281 | @@ -322,7 +314,6 @@ |
282 | <record model="ir.ui.view" id="view_bank_statement_line_tree"> |
283 | <field name="name">Bank statement line tree view</field> |
284 | <field name="model">account.bank.statement.line</field> |
285 | - <field name="type">tree</field> |
286 | <field name="arch" type="xml"> |
287 | <tree string="Statement lines" colors="black:state == 'confirmed';darkmagenta:match_multi == True;crimson:duplicate == True;grey:state=='draft';"> |
288 | <field name="sequence" readonly="1" invisible="1"/> |
289 | |
290 | === modified file 'account_banking/banking_import_transaction.py' |
291 | --- account_banking/banking_import_transaction.py 2013-06-10 10:14:31 +0000 |
292 | +++ account_banking/banking_import_transaction.py 2013-06-26 21:16:23 +0000 |
293 | @@ -62,7 +62,7 @@ |
294 | return [] |
295 | |
296 | digits = dp.get_precision('Account')(cr)[1] |
297 | - amount = round(abs(trans.transferred_amount), digits) |
298 | + amount = round(abs(trans.statement_line_id.amount), digits) |
299 | # Make sure to be able to pinpoint our costs invoice for later |
300 | # matching |
301 | reference = '%s.%s: %s' % (trans.statement, trans.transaction, trans.reference) |
302 | @@ -233,10 +233,6 @@ |
303 | digits = dp.get_precision('Account')(cr)[1] |
304 | partial = False |
305 | |
306 | - # Disabled splitting transactions for now |
307 | - # TODO allow splitting in the interactive wizard |
308 | - allow_splitting = False |
309 | - |
310 | # Search invoice on partner |
311 | if partner_ids: |
312 | candidates = [ |
313 | @@ -276,7 +272,7 @@ |
314 | candidates = [ |
315 | x for x in move_lines |
316 | if (is_zero(x.move_id, ((x.debit or 0.0) - (x.credit or 0.0)) - |
317 | - trans.transferred_amount) |
318 | + trans.statement_line_id.amount) |
319 | and convert.str2date(x.date, '%Y-%m-%d') <= |
320 | (convert.str2date(trans.execution_date, '%Y-%m-%d') + |
321 | self.payment_window) |
322 | @@ -292,7 +288,7 @@ |
323 | # TODO: currency coercing |
324 | best = [x for x in candidates |
325 | if (is_zero(x.move_id, ((x.debit or 0.0) - (x.credit or 0.0)) - |
326 | - trans.transferred_amount) |
327 | + trans.statement_line_id.amount) |
328 | and convert.str2date(x.date, '%Y-%m-%d') <= |
329 | (convert.str2date(trans.execution_date, '%Y-%m-%d') + |
330 | self.payment_window)) |
331 | @@ -343,7 +339,7 @@ |
332 | |
333 | trans2 = None |
334 | if move_line and partial: |
335 | - found = round(trans.transferred_amount, digits) |
336 | + found = round(trans.statement_line_id.amount, digits) |
337 | if abs(expected) == abs(found): |
338 | partial = False |
339 | # Last partial payment will not flag invoice paid without |
340 | @@ -358,24 +354,6 @@ |
341 | elif abs(expected) > abs(found): |
342 | # Partial payment, reuse invoice |
343 | _cache(move_line, expected - found) |
344 | - elif abs(expected) < abs(found) and allow_splitting: |
345 | - # Possible combined payments, need to split transaction to |
346 | - # verify |
347 | - _cache(move_line) |
348 | - trans2 = self.copy( |
349 | - cr, uid, trans.id, |
350 | - dict( |
351 | - transferred_amount = trans.transferred_amount - expected, |
352 | - transaction = trans.transaction + 'b', |
353 | - parent_id = trans.id, |
354 | - ), context=context) |
355 | - # update the current record |
356 | - self.write(cr, uid, trans.id, dict( |
357 | - transferred_amount = expected, |
358 | - transaction = trans.transaction + 'a', |
359 | - ), context) |
360 | - # rebrowse the current record after writing |
361 | - trans = self.browse(cr, uid, trans.id, context=context) |
362 | if move_line: |
363 | account_ids = [ |
364 | x.id for x in bank_account_ids |
365 | @@ -712,7 +690,7 @@ |
366 | # due to float representation and rounding difficulties |
367 | for trans in self.browse(cr, uid, ids, context=context): |
368 | if self.pool.get('res.currency').is_zero( |
369 | - cr, uid, |
370 | + cr, uid, |
371 | trans.statement_id.currency, |
372 | me['transferred_amount'] - trans.transferred_amount): |
373 | dupes.append(trans.id) |
374 | @@ -810,6 +788,12 @@ |
375 | move_info['invoice_ids'][0] |
376 | ) |
377 | return vals |
378 | + |
379 | + def hook_match_payment(self, cr, uid, transaction, log, context=None): |
380 | + """ |
381 | + To override in module 'account_banking_payment' |
382 | + """ |
383 | + return False |
384 | |
385 | def match(self, cr, uid, ids, results=None, context=None): |
386 | if not ids: |
387 | @@ -872,12 +856,6 @@ |
388 | else: |
389 | transaction = transactions[i] |
390 | |
391 | - if (transaction.statement_line_id and |
392 | - transaction.statement_line_id.state == 'confirmed'): |
393 | - raise orm.except_orm( |
394 | - _("Cannot perform match"), |
395 | - _("Cannot perform match on a confirmed transction")) |
396 | - |
397 | if transaction.local_account in error_accounts: |
398 | results['trans_skipped_cnt'] += 1 |
399 | if not injected: |
400 | @@ -962,6 +940,44 @@ |
401 | else: |
402 | info[transaction.local_account][currency_code] = account_info |
403 | |
404 | + # Link accounting period |
405 | + period_id = banktools.get_period( |
406 | + self.pool, cr, uid, transaction.effective_date, |
407 | + company, results['log']) |
408 | + if not period_id: |
409 | + results['trans_skipped_cnt'] += 1 |
410 | + if not injected: |
411 | + i += 1 |
412 | + continue |
413 | + |
414 | + if transaction.statement_line_id: |
415 | + if transaction.statement_line_id.state == 'confirmed': |
416 | + raise orm.except_orm( |
417 | + _("Cannot perform match"), |
418 | + _("Cannot perform match on a confirmed transction")) |
419 | + else: |
420 | + values = { |
421 | + 'name': '%s.%s' % (transaction.statement, transaction.transaction), |
422 | + 'date': transaction.effective_date, |
423 | + 'amount': transaction.transferred_amount, |
424 | + 'statement_id': transaction.statement_id.id, |
425 | + 'note': transaction.message, |
426 | + 'ref': transaction.reference, |
427 | + 'period_id': period_id, |
428 | + 'currency': account_info.currency_id.id, |
429 | + 'import_transaction_id': transaction.id, |
430 | + 'account_id': ( |
431 | + transaction.transferred_amount < 0 and |
432 | + account_info.default_credit_account_id.id or |
433 | + account_info.default_debit_account_id.id), |
434 | + } |
435 | + statement_line_id = statement_line_obj.create(cr, uid, values, context) |
436 | + results['trans_loaded_cnt'] += 1 |
437 | + transaction.write({'statement_line_id': statement_line_id}) |
438 | + transaction.refresh() |
439 | + if transaction.statement_id.id not in imported_statement_ids: |
440 | + imported_statement_ids.append(transaction.statement_id.id) |
441 | + |
442 | # Final check: no coercion of currencies! |
443 | if transaction.local_currency \ |
444 | and account_info.currency_id.name != transaction.local_currency: |
445 | @@ -971,8 +987,8 @@ |
446 | ' uses different currency than the defined bank journal.' |
447 | ) % { |
448 | 'bank_account': transactions.local_account, |
449 | - 'transaction_id': transaction.statement, |
450 | - 'statement_id': transaction.transaction, |
451 | + 'statement_id': transaction.statement, |
452 | + 'transaction_id': transaction.transaction, |
453 | } |
454 | ) |
455 | error_accounts[transaction.local_account] = True |
456 | @@ -981,16 +997,6 @@ |
457 | i += 1 |
458 | continue |
459 | |
460 | - # Link accounting period |
461 | - period_id = banktools.get_period( |
462 | - self.pool, cr, uid, transaction.effective_date, |
463 | - company, results['log']) |
464 | - if not period_id: |
465 | - results['trans_skipped_cnt'] += 1 |
466 | - if not injected: |
467 | - i += 1 |
468 | - continue |
469 | - |
470 | # When bank costs are part of transaction itself, split it. |
471 | if transaction.type != bt.BANK_COSTS and transaction.provision_costs: |
472 | # Create new transaction for bank costs |
473 | @@ -1022,13 +1028,12 @@ |
474 | ), context=context) |
475 | # rebrowse the current record after writing |
476 | transaction = self.browse(cr, uid, transaction.id, context=context) |
477 | - # Match full direct debit orders |
478 | - if transaction.type == bt.DIRECT_DEBIT and has_payment: |
479 | - move_info = self._match_debit_order( |
480 | - cr, uid, transaction, results['log'], context) |
481 | - if transaction.type == bt.STORNO and has_payment: |
482 | - move_info = self._match_storno( |
483 | - cr, uid, transaction, results['log'], context) |
484 | + |
485 | + # Match payment and direct debit orders |
486 | + move_info_payment = self.hook_match_payment( |
487 | + cr, uid, transaction, results['log'], context=context) |
488 | + if move_info_payment: |
489 | + move_info = move_info_payment |
490 | |
491 | # Allow inclusion of generated bank invoices |
492 | if transaction.type == bt.BANK_COSTS: |
493 | @@ -1075,7 +1080,7 @@ |
494 | |
495 | # Credit means payment... isn't it? |
496 | if (not move_info |
497 | - and transaction.transferred_amount < 0 and payment_lines): |
498 | + and transaction.statement_line_id.amount < 0 and payment_lines): |
499 | # Link open payment - if any |
500 | # Note that _match_payment is defined in the |
501 | # account_banking_payment module which should be installed |
502 | @@ -1106,7 +1111,7 @@ |
503 | # settings to overrule this. Note that you need to change |
504 | # the internal type of these accounts to either 'payable' |
505 | # or 'receivable' to enable usage like this. |
506 | - if transaction.transferred_amount < 0: |
507 | + if transaction.statement_line_id.amount < 0: |
508 | if len(partner_banks) == 1: |
509 | account_id = ( |
510 | partner_banks[0].partner_id.property_account_payable and |
511 | @@ -1122,7 +1127,7 @@ |
512 | if len(partner_banks) != 1 or not account_id or account_id == def_rec_account_id: |
513 | account_id = (account_info.default_debit_account_id and |
514 | account_info.default_debit_account_id.id) |
515 | - values = {} |
516 | + values = {'account_id': account_id} |
517 | self_values = {} |
518 | if move_info: |
519 | results['trans_matched_cnt'] += 1 |
520 | @@ -1140,28 +1145,8 @@ |
521 | len(partner_banks) == 1): |
522 | values['partner_bank_id'] = partner_banks[0].id |
523 | |
524 | - if not transaction.statement_line_id: |
525 | - values.update(dict( |
526 | - name = '%s.%s' % (transaction.statement, transaction.transaction), |
527 | - date = transaction.effective_date, |
528 | - amount = transaction.transferred_amount, |
529 | - statement_id = transaction.statement_id.id, |
530 | - note = transaction.message, |
531 | - ref = transaction.reference, |
532 | - period_id = period_id, |
533 | - currency = account_info.currency_id.id, |
534 | - account_id = account_id, |
535 | - import_transaction_id = transaction.id, |
536 | - )) |
537 | - |
538 | - statement_line_id = statement_line_obj.create(cr, uid, values, context) |
539 | - results['trans_loaded_cnt'] += 1 |
540 | - self_values['statement_line_id'] = statement_line_id |
541 | - if transaction.statement_id.id not in imported_statement_ids: |
542 | - imported_statement_ids.append(transaction.statement_id.id) |
543 | - else: |
544 | - statement_line_obj.write( |
545 | - cr, uid, transaction.statement_line_id.id, values, context) |
546 | + statement_line_obj.write( |
547 | + cr, uid, transaction.statement_line_id.id, values, context) |
548 | self.write(cr, uid, transaction.id, self_values, context) |
549 | if not injected: |
550 | i += 1 |
551 | @@ -1350,9 +1335,16 @@ |
552 | 'parent_id': fields.many2one( |
553 | 'banking.import.transaction', 'Split off from this transaction'), |
554 | # match fields |
555 | - 'match_type': fields.selection( |
556 | - [('manual', 'Manual'), ('move','Move'), ('invoice', 'Invoice'), |
557 | - ], 'Match type'), |
558 | + 'match_type': fields.selection([ |
559 | + ('move','Move'), |
560 | + ('invoice', 'Invoice'), |
561 | + ('payment', 'Payment line'), |
562 | + ('payment_order', 'Payment order'), |
563 | + ('storno', 'Storno'), |
564 | + ('manual', 'Manual'), |
565 | + ('payment_manual', 'Payment line (manual)'), |
566 | + ('payment_order_manual', 'Payment order (manual)'), |
567 | + ], 'Match type'), |
568 | 'match_multi': fields.function( |
569 | _get_match_multi, method=True, string='Multi match', |
570 | type='boolean'), |
571 | @@ -1439,9 +1431,16 @@ |
572 | string='Possible duplicate import', readonly=True), |
573 | 'match_type': fields.related( |
574 | 'import_transaction_id', 'match_type', type='selection', |
575 | - selection=[('manual', 'Manual'), ('move','Move'), |
576 | - ('invoice', 'Invoice'), |
577 | - ], |
578 | + selection=[ |
579 | + ('move','Move'), |
580 | + ('invoice', 'Invoice'), |
581 | + ('payment', 'Payment line'), |
582 | + ('payment_order', 'Payment order'), |
583 | + ('storno', 'Storno'), |
584 | + ('manual', 'Manual'), |
585 | + ('payment_manual', 'Payment line (manual)'), |
586 | + ('payment_order_manual', 'Payment order (manual)'), |
587 | + ], |
588 | string='Match type', readonly=True,), |
589 | 'state': fields.selection( |
590 | [('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State', |
591 | @@ -1755,14 +1754,14 @@ |
592 | class account_bank_statement(orm.Model): |
593 | _inherit = 'account.bank.statement' |
594 | |
595 | - def _end_balance(self, cursor, user, ids, name, attr, context=None): |
596 | + def _end_balance(self, cr, uid, ids, name, attr, context=None): |
597 | """ |
598 | This method taken from account/account_bank_statement.py and |
599 | altered to take the statement line subflow into account |
600 | """ |
601 | res = {} |
602 | |
603 | - statements = self.browse(cursor, user, ids, context=context) |
604 | + statements = self.browse(cr, uid, ids, context=context) |
605 | for statement in statements: |
606 | res[statement.id] = statement.balance_start |
607 | |
608 | |
609 | === modified file 'account_banking/wizard/bank_import.py' |
610 | --- account_banking/wizard/bank_import.py 2013-04-27 10:14:24 +0000 |
611 | +++ account_banking/wizard/bank_import.py 2013-06-26 21:16:23 +0000 |
612 | @@ -28,9 +28,9 @@ |
613 | The parsing is done in the parser modules. Every parser module is required to |
614 | use parser.models as a mean of communication with the business logic. |
615 | ''' |
616 | -from osv import orm, fields |
617 | import base64 |
618 | import datetime |
619 | +from openerp.osv import orm, fields |
620 | from openerp.tools.translate import _ |
621 | from openerp.addons.account_banking.parsers import models |
622 | from openerp.addons.account_banking.parsers import convert |
623 | @@ -97,13 +97,13 @@ |
624 | class banking_import(orm.TransientModel): |
625 | _name = 'account.banking.bank.import' |
626 | |
627 | - def import_statements_file(self, cursor, uid, ids, context): |
628 | + def import_statements_file(self, cr, uid, ids, context): |
629 | ''' |
630 | Import bank statements / bank transactions file. |
631 | This method is a wrapper for the business logic on the transaction. |
632 | The parser modules represent the decoding logic. |
633 | ''' |
634 | - banking_import = self.browse(cursor, uid, ids, context)[0] |
635 | + banking_import = self.browse(cr, uid, ids, context)[0] |
636 | statements_file = banking_import.file |
637 | data = base64.decodestring(statements_file) |
638 | |
639 | @@ -125,10 +125,10 @@ |
640 | |
641 | # Get the company |
642 | company = (banking_import.company or |
643 | - user_obj.browse(cursor, uid, uid, context).company_id) |
644 | + user_obj.browse(cr, uid, uid, context).company_id) |
645 | |
646 | # Parse the file |
647 | - statements = parser.parse(cursor, data) |
648 | + statements = parser.parse(cr, data) |
649 | |
650 | if any([x for x in statements if not x.is_valid()]): |
651 | raise orm.except_orm( |
652 | @@ -137,7 +137,7 @@ |
653 | ) |
654 | |
655 | # Create the file now, as the statements need to be linked to it |
656 | - import_id = statement_file_obj.create(cursor, uid, dict( |
657 | + import_id = statement_file_obj.create(cr, uid, dict( |
658 | company_id = company.id, |
659 | file = statements_file, |
660 | state = 'unfinished', |
661 | @@ -184,7 +184,7 @@ |
662 | else: |
663 | # Pull account info/currency |
664 | account_info = banktools.get_company_bank_account( |
665 | - self.pool, cursor, uid, statement.local_account, |
666 | + self.pool, cr, uid, statement.local_account, |
667 | statement.local_currency, company, results.log |
668 | ) |
669 | if not account_info: |
670 | @@ -238,7 +238,7 @@ |
671 | # (e.g. a datetime string of the moment of import) |
672 | # and have potential duplicates flagged by the |
673 | # matching procedure |
674 | - statement_ids = statement_obj.search(cursor, uid, [ |
675 | + statement_ids = statement_obj.search(cr, uid, [ |
676 | ('name', '=', statement.id), |
677 | ('date', '=', convert.date2str(statement.date)), |
678 | ]) |
679 | @@ -252,7 +252,7 @@ |
680 | |
681 | # Get the period for the statement (as bank statement object checks this) |
682 | period_ids = period_obj.search( |
683 | - cursor, uid, [ |
684 | + cr, uid, [ |
685 | ('company_id', '=', company.id), |
686 | ('date_start', '<=', statement.date), |
687 | ('date_stop', '>=', statement.date), |
688 | @@ -270,7 +270,7 @@ |
689 | continue |
690 | |
691 | # Create the bank statement record |
692 | - statement_id = statement_obj.create(cursor, uid, dict( |
693 | + statement_id = statement_obj.create(cr, uid, dict( |
694 | name = statement.id, |
695 | journal_id = account_info.journal_id.id, |
696 | date = convert.date2str(statement.date), |
697 | @@ -302,21 +302,21 @@ |
698 | values['local_currency'] = statement.local_currency |
699 | |
700 | transaction_id = import_transaction_obj.create( |
701 | - cursor, uid, values, context=context) |
702 | + cr, uid, values, context=context) |
703 | transaction_ids.append(transaction_id) |
704 | |
705 | results.stat_loaded_cnt += 1 |
706 | |
707 | - import_transaction_obj.match(cursor, uid, transaction_ids, results=results, context=context) |
708 | + import_transaction_obj.match(cr, uid, transaction_ids, results=results, context=context) |
709 | |
710 | #recompute statement end_balance for validation |
711 | statement_obj.button_dummy( |
712 | - cursor, uid, imported_statement_ids, context=context) |
713 | + cr, uid, imported_statement_ids, context=context) |
714 | |
715 | |
716 | # Original code. Didn't take workflow logistics into account... |
717 | # |
718 | - #cursor.execute( |
719 | + #cr.execute( |
720 | # "UPDATE payment_order o " |
721 | # "SET state = 'done', " |
722 | # "date_done = '%s' " |
723 | @@ -358,13 +358,13 @@ |
724 | ] |
725 | text_log = '\n'.join(report + results.log) |
726 | state = results.error_cnt and 'error' or 'ready' |
727 | - statement_file_obj.write(cursor, uid, import_id, dict( |
728 | + statement_file_obj.write(cr, uid, import_id, dict( |
729 | state = state, log = text_log, |
730 | ), context) |
731 | if not imported_statement_ids or not results.trans_loaded_cnt: |
732 | # file state can be 'ready' while import state is 'error' |
733 | state = 'error' |
734 | - self.write(cursor, uid, [ids[0]], dict( |
735 | + self.write(cr, uid, [ids[0]], dict( |
736 | import_id = import_id, log = text_log, state = state, |
737 | statement_ids = [(6, 0, imported_statement_ids)], |
738 | ), context) |
739 | |
740 | === modified file 'account_banking/wizard/bank_import_view.xml' |
741 | --- account_banking/wizard/bank_import_view.xml 2012-05-02 15:09:49 +0000 |
742 | +++ account_banking/wizard/bank_import_view.xml 2013-06-26 21:16:23 +0000 |
743 | @@ -4,7 +4,6 @@ |
744 | <record id="view_banking_import" model="ir.ui.view"> |
745 | <field name="name">account.banking.bank.import</field> |
746 | <field name="model">account.banking.bank.import</field> |
747 | - <field name="type">form</field> |
748 | <field name="arch" type="xml"> |
749 | <form string="Import Bank Transactions File"> |
750 | <group colspan="4" states="init,ready,error"> |
751 | |
752 | === modified file 'account_banking/wizard/banking_transaction_wizard.py' |
753 | --- account_banking/wizard/banking_transaction_wizard.py 2013-06-10 10:14:31 +0000 |
754 | +++ account_banking/wizard/banking_transaction_wizard.py 2013-06-26 21:16:23 +0000 |
755 | @@ -90,56 +90,33 @@ |
756 | statement_line_obj = self.pool.get('account.bank.statement.line') |
757 | transaction_obj = self.pool.get('banking.import.transaction') |
758 | |
759 | - if not vals: |
760 | + if not vals or not ids: |
761 | return True |
762 | |
763 | + wiz = self.browse(cr, uid, ids[0], context=context) |
764 | + |
765 | # The following fields get never written |
766 | # they are just triggers for manual matching |
767 | # which populates regular fields on the transaction |
768 | manual_invoice_ids = vals.pop('manual_invoice_ids', []) |
769 | manual_move_line_ids = vals.pop('manual_move_line_ids', []) |
770 | |
771 | - # Support for writing fields.related is still flakey: |
772 | - # https://bugs.launchpad.net/openobject-server/+bug/915975 |
773 | - # Will do so myself. |
774 | - |
775 | - # Separate the related fields |
776 | - transaction_vals = {} |
777 | - wizard_vals = vals.copy() |
778 | - for key in vals.keys(): |
779 | - field = self._columns[key] |
780 | - if (isinstance(field, fields.related) and |
781 | - field._arg[0] == 'import_transaction_id'): |
782 | - transaction_vals[field._arg[1]] = vals[key] |
783 | - del wizard_vals[key] |
784 | - |
785 | - # write the related fields on the transaction model |
786 | - if isinstance(ids, int): |
787 | - ids = [ids] |
788 | - for wizard in self.browse(cr, uid, ids, context=context): |
789 | - if wizard.import_transaction_id: |
790 | - transaction_obj.write( |
791 | - cr, uid, wizard.import_transaction_id.id, |
792 | - transaction_vals, context=context) |
793 | - |
794 | - # write other fields to the wizard model |
795 | res = super(banking_transaction_wizard, self).write( |
796 | - cr, uid, ids, wizard_vals, context=context) |
797 | + cr, uid, ids, vals, context=context) |
798 | + wiz.refresh() |
799 | |
800 | - # End of workaround for lp:915975 |
801 | - |
802 | - """ Process the logic of the written values """ |
803 | + # Process the logic of the written values |
804 | |
805 | # An invoice is selected from multiple candidates |
806 | if vals and 'invoice_id' in vals: |
807 | - for wiz in self.browse(cr, uid, ids, context=context): |
808 | - if (wiz.import_transaction_id.match_type == 'invoice' and |
809 | + if (wiz.import_transaction_id.match_type == 'invoice' and |
810 | wiz.import_transaction_id.invoice_id): |
811 | - # the current value might apply |
812 | - if (wiz.move_line_id and wiz.move_line_id.invoice and |
813 | - wiz.move_line_id.invoice.id == wiz.invoice_id.id): |
814 | - found = True |
815 | - continue |
816 | + found = False |
817 | + # the current value might apply |
818 | + if (wiz.move_line_id and wiz.move_line_id.invoice and |
819 | + wiz.move_line_id.invoice == wiz.invoice_id): |
820 | + found = True |
821 | + else: |
822 | # Otherwise, retrieve the move line for this invoice |
823 | # Given the arity of the relation, there is are always |
824 | # multiple possibilities but the move lines here are |
825 | @@ -147,8 +124,8 @@ |
826 | # and the regular invoice workflow should only come up with |
827 | # one of those only. |
828 | for move_line in wiz.import_transaction_id.move_line_ids: |
829 | - if (move_line.invoice.id == |
830 | - wiz.import_transaction_id.invoice_id.id): |
831 | + if (move_line.invoice == |
832 | + wiz.import_transaction_id.invoice_id): |
833 | transaction_obj.write( |
834 | cr, uid, wiz.import_transaction_id.id, |
835 | { 'move_line_id': move_line.id, }, context=context) |
836 | @@ -159,15 +136,12 @@ |
837 | }, context=context) |
838 | found = True |
839 | break |
840 | - # Cannot match the invoice |
841 | - if not found: |
842 | - # transaction_obj.write( |
843 | - # cr, uid, wiz.import_transaction_id.id, |
844 | - # { 'invoice_id': False, }, context=context) |
845 | - orm.except_orm( |
846 | - _("No entry found for the selected invoice"), |
847 | - _("No entry found for the selected invoice. " + |
848 | - "Try manual reconciliation.")) |
849 | + # Cannot match the invoice |
850 | + if not found: |
851 | + orm.except_orm( |
852 | + _("No entry found for the selected invoice"), |
853 | + _("No entry found for the selected invoice. " + |
854 | + "Try manual reconciliation.")) |
855 | |
856 | if manual_move_line_ids or manual_invoice_ids: |
857 | move_line_obj = self.pool.get('account.move.line') |
858 | @@ -323,24 +297,9 @@ |
859 | {'duplicate': not wiz['duplicate']}, context=context) |
860 | return self.create_act_window(cr, uid, ids, context=None) |
861 | |
862 | - def _get_default_match_type(self, cr, uid, context=None): |
863 | - """ |
864 | - Take initial value for the match type from the statement line |
865 | - """ |
866 | - res = False |
867 | - if context and 'statement_line_id' in context: |
868 | - res = self.pool.get('account.bank.statement.line').read( |
869 | - cr, uid, context['statement_line_id'], |
870 | - ['match_type'], context=context)['match_type'] |
871 | - return res |
872 | - |
873 | def button_done(self, cr, uid, ids, context=None): |
874 | return {'type': 'ir.actions.act_window_close'} |
875 | |
876 | - _defaults = { |
877 | -# 'match_type': _get_default_match_type, |
878 | - } |
879 | - |
880 | _columns = { |
881 | 'name': fields.char('Name', size=64), |
882 | 'statement_line_id': fields.many2one( |
883 | @@ -392,8 +351,25 @@ |
884 | 'import_transaction_id', 'match_multi', |
885 | type="boolean", string='Multiple matches'), |
886 | 'match_type': fields.related( |
887 | - 'import_transaction_id', 'match_type', |
888 | - type="char", size=16, string='Match type', readonly=True), |
889 | + 'import_transaction_id', 'match_type', type='selection', |
890 | + selection=[ |
891 | + ('move','Move'), |
892 | + ('invoice', 'Invoice'), |
893 | + ('payment', 'Payment line'), |
894 | + ('payment_order', 'Payment order'), |
895 | + ('storno', 'Storno'), |
896 | + ('manual', 'Manual'), |
897 | + ('payment_manual', 'Payment line (manual)'), |
898 | + ('payment_order_manual', 'Payment order (manual)'), |
899 | + ], |
900 | + string='Match type', readonly=True), |
901 | + 'manual_invoice_id': fields.many2one( |
902 | + 'account.invoice', 'Match this invoice', |
903 | + domain=[('reconciled', '=', False)]), |
904 | + 'manual_move_line_id': fields.many2one( |
905 | + 'account.move.line', 'Or match this entry', |
906 | + domain=[('account_id.reconcile', '=', True), |
907 | + ('reconcile_id', '=', False)]), |
908 | 'manual_invoice_ids': fields.many2many( |
909 | 'account.invoice', |
910 | 'banking_transaction_wizard_account_invoice_rel', |
911 | @@ -417,8 +393,6 @@ |
912 | string="Analytic Account"), |
913 | 'move_currency_amount': fields.related('import_transaction_id','move_currency_amount', |
914 | type='float', string='Match Currency Amount', readonly=True), |
915 | - #'manual_payment_order_id': fields.many2one( |
916 | - # 'payment.order', "Payment order to reconcile"), |
917 | } |
918 | |
919 | banking_transaction_wizard() |
920 | |
921 | === modified file 'account_banking/wizard/banking_transaction_wizard.xml' |
922 | --- account_banking/wizard/banking_transaction_wizard.xml 2013-05-01 15:12:53 +0000 |
923 | +++ account_banking/wizard/banking_transaction_wizard.xml 2013-06-26 21:16:23 +0000 |
924 | @@ -3,7 +3,6 @@ |
925 | <data> |
926 | <record model="ir.ui.view" id="transaction_wizard_first"> |
927 | <field name="name">transaction.wizard.first</field> |
928 | - <field name="type">form</field> |
929 | <field name="model">banking.transaction.wizard</field> |
930 | <field name="arch" type="xml"> |
931 | <form string="Match transaction"> |
932 | |
933 | === modified file 'account_banking/wizard/banktools.py' |
934 | --- account_banking/wizard/banktools.py 2013-05-01 14:25:04 +0000 |
935 | +++ account_banking/wizard/banktools.py 2013-06-26 21:16:23 +0000 |
936 | @@ -51,7 +51,7 @@ |
937 | return False |
938 | return period_ids[0] |
939 | |
940 | -def get_bank_accounts(pool, cursor, uid, account_number, log, fail=False): |
941 | +def get_bank_accounts(pool, cr, uid, account_number, log, fail=False): |
942 | ''' |
943 | Get the bank account with account number account_number |
944 | ''' |
945 | @@ -60,13 +60,13 @@ |
946 | return [] |
947 | |
948 | partner_bank_obj = pool.get('res.partner.bank') |
949 | - bank_account_ids = partner_bank_obj.search(cursor, uid, [ |
950 | + bank_account_ids = partner_bank_obj.search(cr, uid, [ |
951 | ('acc_number', '=', account_number) |
952 | ]) |
953 | if not bank_account_ids: |
954 | # SR 2012-02-19 does the search() override in res_partner_bank |
955 | # provides this result on the previous query? |
956 | - bank_account_ids = partner_bank_obj.search(cursor, uid, [ |
957 | + bank_account_ids = partner_bank_obj.search(cr, uid, [ |
958 | ('acc_number_domestic', '=', account_number) |
959 | ]) |
960 | if not bank_account_ids: |
961 | @@ -76,7 +76,7 @@ |
962 | % dict(account_no=account_number) |
963 | ) |
964 | return [] |
965 | - return partner_bank_obj.browse(cursor, uid, bank_account_ids) |
966 | + return partner_bank_obj.browse(cr, uid, bank_account_ids) |
967 | |
968 | def _has_attr(obj, attr): |
969 | # Needed for dangling addresses and a weird exception scheme in |
970 | @@ -129,14 +129,14 @@ |
971 | 'name %(name)s') % {'name': name}) |
972 | return partner_ids and partner_ids[0] or False |
973 | |
974 | -def get_company_bank_account(pool, cursor, uid, account_number, currency, |
975 | +def get_company_bank_account(pool, cr, uid, account_number, currency, |
976 | company, log): |
977 | ''' |
978 | Get the matching bank account for this company. Currency is the ISO code |
979 | for the requested currency. |
980 | ''' |
981 | results = struct() |
982 | - bank_accounts = get_bank_accounts(pool, cursor, uid, account_number, log, |
983 | + bank_accounts = get_bank_accounts(pool, cr, uid, account_number, log, |
984 | fail=True) |
985 | if not bank_accounts: |
986 | return False |
987 | @@ -159,12 +159,12 @@ |
988 | |
989 | # Find matching journal for currency |
990 | journal_obj = pool.get('account.journal') |
991 | - journal_ids = journal_obj.search(cursor, uid, [ |
992 | + journal_ids = journal_obj.search(cr, uid, [ |
993 | ('type', '=', 'bank'), |
994 | ('currency.name', '=', currency or company.currency_id.name) |
995 | ]) |
996 | if currency == company.currency_id.name: |
997 | - journal_ids_no_curr = journal_obj.search(cursor, uid, [ |
998 | + journal_ids_no_curr = journal_obj.search(cr, uid, [ |
999 | ('type', '=', 'bank'), ('currency', '=', False) |
1000 | ]) |
1001 | journal_ids.extend(journal_ids_no_curr) |
1002 | @@ -172,9 +172,9 @@ |
1003 | criteria.append(('journal_id', 'in', journal_ids)) |
1004 | |
1005 | # Find bank account settings |
1006 | - bank_settings_ids = bank_settings_obj.search(cursor, uid, criteria) |
1007 | + bank_settings_ids = bank_settings_obj.search(cr, uid, criteria) |
1008 | if bank_settings_ids: |
1009 | - settings = bank_settings_obj.browse(cursor, uid, bank_settings_ids)[0] |
1010 | + settings = bank_settings_obj.browse(cr, uid, bank_settings_ids)[0] |
1011 | results.company_id = company |
1012 | results.journal_id = settings.journal_id |
1013 | |
1014 | @@ -192,7 +192,7 @@ |
1015 | |
1016 | return results |
1017 | |
1018 | -def get_or_create_bank(pool, cursor, uid, bic, online=False, code=None, |
1019 | +def get_or_create_bank(pool, cr, uid, bic, online=False, code=None, |
1020 | name=None): |
1021 | ''' |
1022 | Find or create the bank with the provided BIC code. |
1023 | @@ -208,27 +208,27 @@ |
1024 | if len(bic) < 8: |
1025 | # search key |
1026 | bank_ids = bank_obj.search( |
1027 | - cursor, uid, [ |
1028 | + cr, uid, [ |
1029 | ('bic', '=', bic[:6]) |
1030 | ]) |
1031 | if not bank_ids: |
1032 | bank_ids = bank_obj.search( |
1033 | - cursor, uid, [ |
1034 | + cr, uid, [ |
1035 | ('bic', 'ilike', bic + '%') |
1036 | ]) |
1037 | else: |
1038 | bank_ids = bank_obj.search( |
1039 | - cursor, uid, [ |
1040 | + cr, uid, [ |
1041 | ('bic', '=', bic) |
1042 | ]) |
1043 | |
1044 | if bank_ids and len(bank_ids) == 1: |
1045 | - banks = bank_obj.browse(cursor, uid, bank_ids) |
1046 | + banks = bank_obj.browse(cr, uid, bank_ids) |
1047 | return banks[0].id, banks[0].country.id |
1048 | |
1049 | country_obj = pool.get('res.country') |
1050 | country_ids = country_obj.search( |
1051 | - cursor, uid, [('code', '=', bic[4:6])] |
1052 | + cr, uid, [('code', '=', bic[4:6])] |
1053 | ) |
1054 | country_id = country_ids and country_ids[0] or False |
1055 | bank_id = False |
1056 | @@ -236,7 +236,7 @@ |
1057 | if online: |
1058 | info, address = sepa.online.bank_info(bic) |
1059 | if info: |
1060 | - bank_id = bank_obj.create(cursor, uid, dict( |
1061 | + bank_id = bank_obj.create(cr, uid, dict( |
1062 | code = info.code, |
1063 | name = info.name, |
1064 | street = address.street, |
1065 | @@ -250,7 +250,7 @@ |
1066 | info = struct(name=name, code=code) |
1067 | |
1068 | if not online or not bank_id: |
1069 | - bank_id = bank_obj.create(cursor, uid, dict( |
1070 | + bank_id = bank_obj.create(cr, uid, dict( |
1071 | code = info.code or 'UNKNOW', |
1072 | name = info.name or _('Unknown Bank'), |
1073 | country = country_id, |
1074 | |
1075 | === modified file 'account_banking_nl_clieop/__openerp__.py' |
1076 | --- account_banking_nl_clieop/__openerp__.py 2013-04-15 14:14:27 +0000 |
1077 | +++ account_banking_nl_clieop/__openerp__.py 2013-06-26 21:16:23 +0000 |
1078 | @@ -37,5 +37,5 @@ |
1079 | ClieOp format is used by Dutch banks to batch national bank transfers. |
1080 | This module uses the account_banking logic. |
1081 | ''', |
1082 | - 'installable': False, |
1083 | + 'installable': True, |
1084 | } |
1085 | |
1086 | === modified file 'account_banking_nl_clieop/account_banking_nl_clieop.py' |
1087 | --- account_banking_nl_clieop/account_banking_nl_clieop.py 2013-04-15 13:59:50 +0000 |
1088 | +++ account_banking_nl_clieop/account_banking_nl_clieop.py 2013-06-26 21:16:23 +0000 |
1089 | @@ -1,6 +1,7 @@ |
1090 | ############################################################################## |
1091 | # |
1092 | # Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>). |
1093 | +# (C) 2011 - 2013 Therp BV (<http://therp.nl>). |
1094 | # All Rights Reserved |
1095 | # |
1096 | # This program is free software: you can redistribute it and/or modify |
1097 | @@ -18,11 +19,12 @@ |
1098 | # |
1099 | ############################################################################## |
1100 | |
1101 | -from osv import osv, fields |
1102 | from datetime import date |
1103 | -from tools.translate import _ |
1104 | - |
1105 | -class clieop_export(osv.osv): |
1106 | +from openerp.osv import orm, fields |
1107 | +from openerp.tools.translate import _ |
1108 | + |
1109 | + |
1110 | +class clieop_export(orm.Model): |
1111 | '''ClieOp3 Export''' |
1112 | _name = 'banking.export.clieop' |
1113 | _description = __doc__ |
1114 | @@ -80,7 +82,7 @@ |
1115 | last = 1 |
1116 | last_ids = self.search(cr, uid, [ |
1117 | ('date_generated', '=', |
1118 | - fields.date.context_today(cr,uid,context)) |
1119 | + fields.date.context_today(self, cr,uid,context)) |
1120 | ], context=context) |
1121 | if last_ids: |
1122 | last = 1 + max([x['daynumber'] for x in self.read( |
1123 | @@ -94,6 +96,3 @@ |
1124 | 'state': 'draft', |
1125 | 'daynumber': get_daynr, |
1126 | } |
1127 | -clieop_export() |
1128 | - |
1129 | -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
1130 | |
1131 | === modified file 'account_banking_nl_clieop/account_banking_nl_clieop.xml' |
1132 | --- account_banking_nl_clieop/account_banking_nl_clieop.xml 2013-01-02 15:14:53 +0000 |
1133 | +++ account_banking_nl_clieop/account_banking_nl_clieop.xml 2013-06-26 21:16:23 +0000 |
1134 | @@ -11,7 +11,6 @@ |
1135 | <record id="view_banking_export_clieop_form" model="ir.ui.view"> |
1136 | <field name="name">account.banking.export.clieop.form</field> |
1137 | <field name="model">banking.export.clieop</field> |
1138 | - <field name="type">form</field> |
1139 | <field name="arch" type="xml"> |
1140 | <form string="Client Opdrachten Export"> |
1141 | <notebook> |
1142 | @@ -48,7 +47,6 @@ |
1143 | <record id="view_banking_export_clieop_tree" model="ir.ui.view"> |
1144 | <field name="name">account.banking.export.clieop.tree</field> |
1145 | <field name="model">banking.export.clieop</field> |
1146 | - <field name="type">tree</field> |
1147 | <field name="arch" type="xml"> |
1148 | <tree string="Client Opdrachten Export"> |
1149 | <field name="filetype" /> |
1150 | |
1151 | === modified file 'account_banking_nl_clieop/wizard/export_clieop.py' |
1152 | --- account_banking_nl_clieop/wizard/export_clieop.py 2013-04-15 13:59:50 +0000 |
1153 | +++ account_banking_nl_clieop/wizard/export_clieop.py 2013-06-26 21:16:23 +0000 |
1154 | @@ -2,6 +2,7 @@ |
1155 | ############################################################################## |
1156 | # |
1157 | # Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>). |
1158 | +# 2011 - 2013 Therp BV (<http://therp.nl>). |
1159 | # All Rights Reserved |
1160 | # |
1161 | # This program is free software: you can redistribute it and/or modify |
1162 | @@ -21,21 +22,22 @@ |
1163 | |
1164 | import base64 |
1165 | from datetime import datetime, date, timedelta |
1166 | -from osv import osv, fields |
1167 | -from tools.translate import _ |
1168 | -import netsvc |
1169 | -from account_banking import sepa |
1170 | -import clieop |
1171 | - |
1172 | -def strpdate(arg, format='%Y-%m-%d'): |
1173 | - '''shortcut''' |
1174 | - return datetime.strptime(arg, format).date() |
1175 | - |
1176 | -def strfdate(arg, format='%Y-%m-%d'): |
1177 | - '''shortcut''' |
1178 | - return arg.strftime(format) |
1179 | - |
1180 | -class banking_export_clieop_wizard(osv.osv_memory): |
1181 | +from openerp.osv import orm, fields |
1182 | +from openerp.tools.translate import _ |
1183 | +from openerp import netsvc |
1184 | +from openerp.tools import DEFAULT_SERVER_DATE_FORMAT |
1185 | +from openerp.addons.account_banking import sepa |
1186 | +from openerp.addons.account_banking_nl_clieop.wizard import clieop |
1187 | + |
1188 | +def strpdate(arg): |
1189 | + '''shortcut''' |
1190 | + return datetime.strptime(arg, DEFAULT_SERVER_DATE_FORMAT).date() |
1191 | + |
1192 | +def strfdate(arg): |
1193 | + '''shortcut''' |
1194 | + return arg.strftime(DEFAULT_SERVER_DATE_FORMAT) |
1195 | + |
1196 | +class banking_export_clieop_wizard(orm.TransientModel): |
1197 | _name = 'banking.export.clieop.wizard' |
1198 | _description = 'Client Opdrachten Export' |
1199 | _columns = { |
1200 | @@ -151,21 +153,17 @@ |
1201 | ), |
1202 | } |
1203 | |
1204 | - _defaults = { |
1205 | - 'test': True, |
1206 | - } |
1207 | - |
1208 | - def create(self, cursor, uid, vals, context=None): |
1209 | + def create(self, cr, uid, vals, context=None): |
1210 | ''' |
1211 | Retrieve a sane set of default values based on the payment orders |
1212 | from the context. |
1213 | ''' |
1214 | if 'batchtype' not in vals: |
1215 | - self.check_orders(cursor, uid, vals, context) |
1216 | + self.check_orders(cr, uid, vals, context) |
1217 | return super(banking_export_clieop_wizard, self).create( |
1218 | - cursor, uid, vals, context) |
1219 | + cr, uid, vals, context) |
1220 | |
1221 | - def check_orders(self, cursor, uid, vals, context): |
1222 | + def check_orders(self, cr, uid, vals, context): |
1223 | ''' |
1224 | Check payment type for all orders. |
1225 | |
1226 | @@ -177,14 +175,14 @@ |
1227 | Also mind that rates for batches are way higher than those for |
1228 | transactions. It pays to limit the number of batches. |
1229 | ''' |
1230 | - today = date.today() |
1231 | + today = strpdate(fields.date.context_today(self, cr, uid, context=context)) |
1232 | payment_order_obj = self.pool.get('payment.order') |
1233 | |
1234 | # Payment order ids are provided in the context |
1235 | payment_order_ids = context.get('active_ids', []) |
1236 | runs = {} |
1237 | # Only orders of same type can be combined |
1238 | - payment_orders = payment_order_obj.browse(cursor, uid, payment_order_ids) |
1239 | + payment_orders = payment_order_obj.browse(cr, uid, payment_order_ids) |
1240 | for payment_order in payment_orders: |
1241 | |
1242 | payment_type = payment_order.mode.type.code |
1243 | @@ -194,8 +192,8 @@ |
1244 | runs[payment_type] = [payment_order] |
1245 | |
1246 | if payment_order.date_prefered == 'fixed': |
1247 | - if payment_order.date_planned: |
1248 | - execution_date = strpdate(payment_order.date_planned) |
1249 | + if payment_order.date_scheduled: |
1250 | + execution_date = strpdate(payment_order.date_scheduled) |
1251 | else: |
1252 | execution_date = today |
1253 | elif payment_order.date_prefered == 'now': |
1254 | @@ -212,12 +210,12 @@ |
1255 | else: |
1256 | execution_date = today |
1257 | if execution_date and execution_date >= max_date: |
1258 | - raise osv.except_osv( |
1259 | + raise orm.except_orm( |
1260 | _('Error'), |
1261 | _('You can\'t create ClieOp orders more than 30 days in advance.') |
1262 | ) |
1263 | if len(runs) != 1: |
1264 | - raise osv.except_osv( |
1265 | + raise orm.except_orm( |
1266 | _('Error'), |
1267 | _('You can only combine payment orders of the same type') |
1268 | ) |
1269 | @@ -231,12 +229,12 @@ |
1270 | 'state': 'create', |
1271 | }) |
1272 | |
1273 | - def create_clieop(self, cursor, uid, ids, context): |
1274 | + def create_clieop(self, cr, uid, ids, context): |
1275 | ''' |
1276 | Wizard to actually create the ClieOp3 file |
1277 | ''' |
1278 | payment_order_obj = self.pool.get('payment.order') |
1279 | - clieop_export = self.browse(cursor, uid, ids, context)[0] |
1280 | + clieop_export = self.browse(cr, uid, ids, context)[0] |
1281 | clieopfile = None |
1282 | for payment_order in clieop_export.payment_order_ids: |
1283 | if not clieopfile: |
1284 | @@ -253,7 +251,7 @@ |
1285 | else: |
1286 | our_account_nr = payment_order.mode.bank_id.acc_number |
1287 | if not our_account_nr: |
1288 | - raise osv.except_osv( |
1289 | + raise orm.except_orm( |
1290 | _('Error'), |
1291 | _('Your bank account has to have a valid account number') |
1292 | ) |
1293 | @@ -267,7 +265,7 @@ |
1294 | accountno_sender = our_account_nr, |
1295 | seqno = self.pool.get( |
1296 | 'banking.export.clieop').get_daynr( |
1297 | - cursor, uid, context=context), |
1298 | + cr, uid, context=context), |
1299 | test = clieop_export['test'] |
1300 | ) |
1301 | |
1302 | @@ -291,7 +289,7 @@ |
1303 | for line in payment_order.line_ids: |
1304 | # Check on missing partner of bank account (this can happen!) |
1305 | if not line.bank_id or not line.bank_id.partner_id: |
1306 | - raise osv.except_osv( |
1307 | + raise orm.except_orm( |
1308 | _('Error'), |
1309 | _('There is insufficient information.\r\n' |
1310 | 'Both destination address and account ' |
1311 | @@ -314,7 +312,7 @@ |
1312 | # Is this an IBAN account? |
1313 | if iban.valid: |
1314 | if iban.countrycode != 'NL': |
1315 | - raise osv.except_osv( |
1316 | + raise orm.except_orm( |
1317 | _('Error'), |
1318 | _('You cannot send international bank transfers ' |
1319 | 'through ClieOp3!') |
1320 | @@ -331,7 +329,7 @@ |
1321 | # Generate the specifics of this clieopfile |
1322 | order = clieopfile.order |
1323 | file_id = self.pool.get('banking.export.clieop').create( |
1324 | - cursor, uid, dict( |
1325 | + cr, uid, dict( |
1326 | filetype = order.name_transactioncode, |
1327 | identification = order.identification, |
1328 | prefered_date = strfdate(order.preferred_execution_date), |
1329 | @@ -346,7 +344,7 @@ |
1330 | [6, 0, [x.id for x in clieop_export['payment_order_ids']]] |
1331 | ], |
1332 | ), context) |
1333 | - self.write(cursor, uid, [ids[0]], dict( |
1334 | + self.write(cr, uid, [ids[0]], dict( |
1335 | filetype = order.name_transactioncode, |
1336 | testcode = order.testcode, |
1337 | file_id = file_id, |
1338 | @@ -364,31 +362,27 @@ |
1339 | 'res_id': ids[0] or False, |
1340 | } |
1341 | |
1342 | - def cancel_clieop(self, cursor, uid, ids, context): |
1343 | + def cancel_clieop(self, cr, uid, ids, context): |
1344 | ''' |
1345 | Cancel the ClieOp: just drop the file |
1346 | ''' |
1347 | - clieop_export = self.read(cursor, uid, ids, ['file_id'], context)[0] |
1348 | - self.pool.get('banking.export.clieop').unlink(cursor, uid, clieop_export['file_id'][0]) |
1349 | + clieop_export = self.read(cr, uid, ids, ['file_id'], context)[0] |
1350 | + self.pool.get('banking.export.clieop').unlink(cr, uid, clieop_export['file_id'][0]) |
1351 | return {'type': 'ir.actions.act_window_close'} |
1352 | |
1353 | - def save_clieop(self, cursor, uid, ids, context): |
1354 | + def save_clieop(self, cr, uid, ids, context): |
1355 | ''' |
1356 | Save the ClieOp: mark all payments in the file as 'sent', if not a test |
1357 | ''' |
1358 | clieop_export = self.browse( |
1359 | - cursor, uid, ids, context)[0] |
1360 | + cr, uid, ids, context)[0] |
1361 | if not clieop_export['test']: |
1362 | clieop_obj = self.pool.get('banking.export.clieop') |
1363 | payment_order_obj = self.pool.get('payment.order') |
1364 | clieop_file = clieop_obj.write( |
1365 | - cursor, uid, clieop_export['file_id'].id, {'state': 'sent'} |
1366 | + cr, uid, clieop_export['file_id'].id, {'state': 'sent'} |
1367 | ) |
1368 | wf_service = netsvc.LocalService('workflow') |
1369 | for order in clieop_export['payment_order_ids']: |
1370 | - wf_service.trg_validate(uid, 'payment.order', order.id, 'sent', cursor) |
1371 | + wf_service.trg_validate(uid, 'payment.order', order.id, 'sent', cr) |
1372 | return {'type': 'ir.actions.act_window_close'} |
1373 | - |
1374 | -banking_export_clieop_wizard() |
1375 | - |
1376 | -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
1377 | |
1378 | === modified file 'account_banking_nl_clieop/wizard/export_clieop_view.xml' |
1379 | --- account_banking_nl_clieop/wizard/export_clieop_view.xml 2013-01-02 15:14:53 +0000 |
1380 | +++ account_banking_nl_clieop/wizard/export_clieop_view.xml 2013-06-26 21:16:23 +0000 |
1381 | @@ -4,7 +4,6 @@ |
1382 | <record id="banking_export_clieop_wizard_view" model="ir.ui.view"> |
1383 | <field name="name">banking.export.clieop.wizard.view</field> |
1384 | <field name="model">banking.export.clieop.wizard</field> |
1385 | - <field name="type">form</field> |
1386 | <field name="arch" type="xml"> |
1387 | <form string="Client Opdrachten Export"> |
1388 | <field name="state" invisible="True"/> |
1389 | |
1390 | === modified file 'account_banking_nl_girotel/girotel.py' |
1391 | --- account_banking_nl_girotel/girotel.py 2013-04-15 13:59:50 +0000 |
1392 | +++ account_banking_nl_girotel/girotel.py 2013-06-26 21:16:23 +0000 |
1393 | @@ -45,6 +45,7 @@ |
1394 | from account_banking.parsers import models |
1395 | from account_banking.parsers.convert import str2date, to_swift |
1396 | from tools.translate import _ |
1397 | +import re |
1398 | import csv |
1399 | |
1400 | bt = models.mem_bank_transaction |
1401 | @@ -105,6 +106,13 @@ |
1402 | self.date = str2date(self.date, '%Y%m%d') |
1403 | if self.direction == 'A': |
1404 | self.transferred_amount = -float(self.transferred_amount) |
1405 | + if (self.transfer_type == 'VZ' |
1406 | + and (not self.remote_account or self.remote_account == '0') |
1407 | + and (not self.message or re.match('^\s*$', self.message)) |
1408 | + and self.remote_owner.startswith('TOTAAL ')): |
1409 | + self.transfer_type = 'PB' |
1410 | + self.message = self.remote_owner |
1411 | + self.remove_owner = False |
1412 | else: |
1413 | self.transferred_amount = float(self.transferred_amount) |
1414 | self.local_account = self.local_account.zfill(10) |
1415 | @@ -140,7 +148,8 @@ |
1416 | 'GT': bt.ORDER, |
1417 | 'IC': bt.DIRECT_DEBIT, |
1418 | 'OV': bt.ORDER, |
1419 | - 'VZ': bt.PAYMENT_BATCH, |
1420 | + 'VZ': bt.ORDER, |
1421 | + 'PB': bt.PAYMENT_BATCH, |
1422 | } |
1423 | |
1424 | def __init__(self, line, *args, **kwargs): |
1425 | @@ -171,11 +180,14 @@ |
1426 | 4. Cash withdrawals from banks are too not seen as a transfer between |
1427 | two accounts - the cash exits the banking system. These withdrawals |
1428 | have their transfer_type set to 'GM'. |
1429 | + 5. Aggregated payment batches. These transactions have transfer type |
1430 | + 'VZ' natively but are changed to 'PB' while parsing. These transactions |
1431 | + have no remote account. |
1432 | ''' |
1433 | return bool(self.transferred_amount and self.execution_date and ( |
1434 | self.remote_account or |
1435 | self.transfer_type in [ |
1436 | - 'DV', 'BT', 'BA', 'GM', |
1437 | + 'DV', 'PB', 'BT', 'BA', 'GM', |
1438 | ])) |
1439 | |
1440 | def refold_message(self, message): |
1441 | |
1442 | === modified file 'account_banking_payment/__openerp__.py' |
1443 | --- account_banking_payment/__openerp__.py 2013-03-17 12:53:37 +0000 |
1444 | +++ account_banking_payment/__openerp__.py 2013-06-26 21:16:23 +0000 |
1445 | @@ -37,6 +37,7 @@ |
1446 | 'data': [ |
1447 | 'view/account_payment.xml', |
1448 | 'view/banking_transaction_wizard.xml', |
1449 | + 'view/payment_mode.xml', |
1450 | 'view/payment_mode_type.xml', |
1451 | 'view/bank_payment_manual.xml', |
1452 | 'data/payment_mode_type.xml', |
1453 | @@ -53,5 +54,5 @@ |
1454 | account_banking_nl_clieop |
1455 | ''', |
1456 | 'auto_install': True, |
1457 | - 'installable': False, |
1458 | + 'installable': True, |
1459 | } |
1460 | |
1461 | === modified file 'account_banking_payment/model/__init__.py' |
1462 | --- account_banking_payment/model/__init__.py 2013-03-16 19:00:59 +0000 |
1463 | +++ account_banking_payment/model/__init__.py 2013-06-26 21:16:23 +0000 |
1464 | @@ -4,7 +4,6 @@ |
1465 | import payment_mode_type |
1466 | import payment_order_create |
1467 | import banking_import_transaction |
1468 | -import account_bank_statement_line |
1469 | import banking_transaction_wizard |
1470 | import bank_payment_manual |
1471 | import banking_import_line |
1472 | |
1473 | === removed file 'account_banking_payment/model/account_bank_statement_line.py' |
1474 | --- account_banking_payment/model/account_bank_statement_line.py 2013-03-17 09:10:15 +0000 |
1475 | +++ account_banking_payment/model/account_bank_statement_line.py 1970-01-01 00:00:00 +0000 |
1476 | @@ -1,40 +0,0 @@ |
1477 | -# -*- coding: utf-8 -*- |
1478 | -############################################################################## |
1479 | -# |
1480 | -# Copyright (C) 2009 EduSense BV (<http://www.edusense.nl>). |
1481 | -# (C) 2011 - 2013 Therp BV (<http://therp.nl>). |
1482 | -# |
1483 | -# All other contributions are (C) by their respective contributors |
1484 | -# |
1485 | -# All Rights Reserved |
1486 | -# |
1487 | -# This program is free software: you can redistribute it and/or modify |
1488 | -# it under the terms of the GNU Affero General Public License as |
1489 | -# published by the Free Software Foundation, either version 3 of the |
1490 | -# License, or (at your option) any later version. |
1491 | -# |
1492 | -# This program is distributed in the hope that it will be useful, |
1493 | -# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1494 | -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
1495 | -# GNU Affero General Public License for more details. |
1496 | -# |
1497 | -# You should have received a copy of the GNU Affero General Public License |
1498 | -# along with this program. If not, see <http://www.gnu.org/licenses/>. |
1499 | -# |
1500 | -############################################################################## |
1501 | - |
1502 | -from openerp.osv import orm, fields |
1503 | - |
1504 | - |
1505 | -class account_bank_statement_line(orm.Model): |
1506 | - _inherit = 'account.bank.statement.line' |
1507 | - _columns = { |
1508 | - 'match_type': fields.related( |
1509 | - # Add payment and storno types |
1510 | - 'import_transaction_id', 'match_type', type='selection', |
1511 | - selection=[('manual', 'Manual'), ('move','Move'), |
1512 | - ('invoice', 'Invoice'), ('payment', 'Payment'), |
1513 | - ('payment_order', 'Payment order'), |
1514 | - ('storno', 'Storno')], |
1515 | - string='Match type', readonly=True,), |
1516 | - } |
1517 | |
1518 | === modified file 'account_banking_payment/model/account_payment.py' |
1519 | --- account_banking_payment/model/account_payment.py 2013-04-06 05:02:18 +0000 |
1520 | +++ account_banking_payment/model/account_payment.py 2013-06-26 21:16:23 +0000 |
1521 | @@ -73,6 +73,8 @@ |
1522 | 'line_ids': fields.one2many( |
1523 | 'payment.line', 'order_id', 'Payment lines', |
1524 | states={ |
1525 | + 'open': [('readonly', True)], |
1526 | + 'cancel': [('readonly', True)], |
1527 | 'sent': [('readonly', True)], |
1528 | 'rejected': [('readonly', True)], |
1529 | 'done': [('readonly', True)] |
1530 | @@ -172,32 +174,10 @@ |
1531 | ]) |
1532 | payment_line_obj.write(cr, uid, line_ids, kwargs) |
1533 | |
1534 | - def set_to_draft(self, cr, uid, ids, *args): |
1535 | - ''' |
1536 | - Set both self and payment lines to state 'draft'. |
1537 | - ''' |
1538 | - self._write_payment_lines(cr, uid, ids, export_state='draft') |
1539 | - return super(payment_order, self).set_to_draft( |
1540 | - cr, uid, ids, *args |
1541 | - ) |
1542 | - |
1543 | - def action_sent(self, cr, uid, ids, context=None): |
1544 | - ''' |
1545 | - Set both self and payment lines to state 'sent'. |
1546 | - ''' |
1547 | - self._write_payment_lines(cr, uid, ids, export_state='sent') |
1548 | - self.write(cr, uid, ids, { |
1549 | - 'state': 'sent', |
1550 | - 'date_sent': fields.date.context_today( |
1551 | - self, cr, uid, context=context), |
1552 | - }, context=context) |
1553 | - return True |
1554 | - |
1555 | def action_rejected(self, cr, uid, ids, *args): |
1556 | ''' |
1557 | Set both self and payment lines to state 'rejected'. |
1558 | ''' |
1559 | - self._write_payment_lines(cr, uid, ids, export_state='rejected') |
1560 | wf_service = netsvc.LocalService('workflow') |
1561 | for id in ids: |
1562 | wf_service.trg_validate(uid, 'payment.order', id, 'rejected', cr) |
1563 | @@ -209,32 +189,172 @@ |
1564 | ''' |
1565 | self._write_payment_lines( |
1566 | cr, uid, ids, |
1567 | - export_state='done', |
1568 | date_done=fields.date.context_today(self, cr, uid)) |
1569 | return super(payment_order, self).set_done( |
1570 | cr, uid, ids, *args |
1571 | ) |
1572 | |
1573 | - """ |
1574 | - Hooks for processing direct debit orders, such as implemented in |
1575 | - account_direct_debit module. |
1576 | - """ |
1577 | - def debit_reconcile_transfer( |
1578 | - self, cr, uid, payment_order_id, amount, currency, context=None): |
1579 | - """ |
1580 | - Reconcile the payment order if the amount is correct. Return the |
1581 | - id of the reconciliation. |
1582 | - """ |
1583 | - raise orm.except_orm( |
1584 | - _("Cannot reconcile"), |
1585 | - _("Cannot reconcile debit order: "+ |
1586 | - "Not implemented.")) |
1587 | - |
1588 | - def debit_unreconcile_transfer( |
1589 | - self, cr, uid, payment_order_id, reconcile_id, amount, currency, |
1590 | - context=None): |
1591 | - """ Unreconcile the payment_order if at all possible """ |
1592 | - raise orm.except_orm( |
1593 | - _("Cannot unreconcile"), |
1594 | - _("Cannot unreconcile debit order: "+ |
1595 | - "Not implemented.")) |
1596 | + def debit_reconcile_transfer(self, cr, uid, payment_order_id, |
1597 | + amount, currency, context=None): |
1598 | + """ |
1599 | + During import of bank statements, create the reconcile on the transfer |
1600 | + account containing all the open move lines on the transfer account. |
1601 | + """ |
1602 | + move_line_obj = self.pool.get('account.move.line') |
1603 | + order = self.browse(cr, uid, payment_order_id, context) |
1604 | + line_ids = [] |
1605 | + reconcile_id = False |
1606 | + if not order.line_ids[0].transit_move_line_id: |
1607 | + wf_service = netsvc.LocalService('workflow') |
1608 | + wf_service.trg_validate( |
1609 | + uid, 'payment.order', payment_order_id, 'done', cr) |
1610 | + return False |
1611 | + for order_line in order.line_ids: |
1612 | + for line in order_line.transit_move_line_id.move_id.line_id: |
1613 | + if line.account_id.type == 'other' and not line.reconcile_id: |
1614 | + line_ids.append(line.id) |
1615 | + if self.pool.get('res.currency').is_zero( |
1616 | + cr, uid, currency, |
1617 | + move_line_obj.get_balance(cr, uid, line_ids) - amount): |
1618 | + reconcile_id = self.pool.get('account.move.reconcile').create( |
1619 | + cr, uid, |
1620 | + {'type': 'auto', 'line_id': [(6, 0, line_ids)]}, |
1621 | + context) |
1622 | + # set direct debit order to finished state |
1623 | + wf_service = netsvc.LocalService('workflow') |
1624 | + wf_service.trg_validate( |
1625 | + uid, 'payment.order', payment_order_id, 'done', cr) |
1626 | + return reconcile_id |
1627 | + |
1628 | + def debit_unreconcile_transfer(self, cr, uid, payment_order_id, reconcile_id, |
1629 | + amount, currency, context=None): |
1630 | + """ |
1631 | + Due to a cancelled bank statements import, unreconcile the move on |
1632 | + the transfer account. Delegate the conditions to the workflow. |
1633 | + Raise on failure for rollback. |
1634 | + |
1635 | + Workflow appears to return False even on success so we just check |
1636 | + the order's state that we know to be set to 'sent' in that case. |
1637 | + """ |
1638 | + self.pool.get('account.move.reconcile').unlink( |
1639 | + cr, uid, [reconcile_id], context=context) |
1640 | + netsvc.LocalService('workflow').trg_validate( |
1641 | + uid, 'payment.order', payment_order_id, 'undo_done', cr) |
1642 | + state = self.pool.get('payment.order').read( |
1643 | + cr, uid, payment_order_id, ['state'], context=context)['state'] |
1644 | + if state != 'sent': |
1645 | + raise orm.except_orm( |
1646 | + _("Cannot unreconcile"), |
1647 | + _("Cannot unreconcile payment order: "+ |
1648 | + "Workflow will not allow it.")) |
1649 | + return True |
1650 | + |
1651 | + def test_undo_done(self, cr, uid, ids, context=None): |
1652 | + """ |
1653 | + Called from the workflow. Used to unset done state on |
1654 | + payment orders that were reconciled with bank transfers |
1655 | + which are being cancelled. |
1656 | + |
1657 | + Test if the payment order has not been reconciled. Depends |
1658 | + on the restriction that transit move lines should use an |
1659 | + account of type 'other', and on the restriction of payment |
1660 | + and debit orders that they only take moves on accounts |
1661 | + payable/receivable. |
1662 | + """ |
1663 | + for order in self.browse(cr, uid, ids, context=context): |
1664 | + for order_line in order.line_ids: |
1665 | + if order_line.transit_move_line_id.move_id: |
1666 | + for line in order_line.transit_move_line_id.move_id.line_id: |
1667 | + if (line.account_id.type == 'other' and |
1668 | + line.reconcile_id): |
1669 | + return False |
1670 | + return True |
1671 | + |
1672 | + def action_sent(self, cr, uid, ids, context=None): |
1673 | + """ |
1674 | + Create the moves that pay off the move lines from |
1675 | + the debit order. This happens when the debit order file is |
1676 | + generated. |
1677 | + """ |
1678 | + account_move_obj = self.pool.get('account.move') |
1679 | + account_move_line_obj = self.pool.get('account.move.line') |
1680 | + payment_line_obj = self.pool.get('payment.line') |
1681 | + labels = { |
1682 | + 'payment': _('Payment order'), |
1683 | + 'debit': _('Direct debit order'), |
1684 | + } |
1685 | + for order in self.browse(cr, uid, ids, context=context): |
1686 | + for line in order.line_ids: |
1687 | + # basic checks |
1688 | + if not line.move_line_id: |
1689 | + raise orm.except_orm( |
1690 | + _('Error'), |
1691 | + _('No move line provided for line %s') % line.name) |
1692 | + if line.move_line_id.reconcile_id: |
1693 | + raise orm.except_orm( |
1694 | + _('Error'), |
1695 | + _('Move line %s has already been paid/reconciled') % |
1696 | + line.move_line_id.name |
1697 | + ) |
1698 | + |
1699 | + move_id = account_move_obj.create(cr, uid, { |
1700 | + 'journal_id': order.mode.transfer_journal_id.id, |
1701 | + 'name': '%s %s' % (labels[order.payment_order_type], |
1702 | + line.move_line_id.move_id.name), |
1703 | + 'reference': '%s%s' % (order.payment_order_type[:3].upper(), |
1704 | + line.move_line_id.move_id.name), |
1705 | + }, context=context) |
1706 | + |
1707 | + # TODO: take multicurrency into account |
1708 | + |
1709 | + # create the debit move line on the transfer account |
1710 | + vals = { |
1711 | + 'name': _('%s for %s') % ( |
1712 | + labels[order.payment_order_type], |
1713 | + line.move_line_id.invoice and |
1714 | + line.move_line_id.invoice.number or |
1715 | + line.move_line_id.name), |
1716 | + 'move_id': move_id, |
1717 | + 'partner_id': line.partner_id.id, |
1718 | + 'account_id': order.mode.transfer_account_id.id, |
1719 | + 'credit': (order.payment_order_type == 'payment' |
1720 | + and line.amount or 0.0), |
1721 | + 'debit': (order.payment_order_type == 'debit' |
1722 | + and line.amount or 0.0), |
1723 | + 'date': fields.date.context_today( |
1724 | + self, cr, uid, context=context), |
1725 | + } |
1726 | + transfer_move_line_id = account_move_line_obj.create( |
1727 | + cr, uid, vals, context=context) |
1728 | + |
1729 | + # create the debit move line on the receivable account |
1730 | + vals.update({ |
1731 | + 'account_id': line.move_line_id.account_id.id, |
1732 | + 'credit': (order.payment_order_type == 'debit' |
1733 | + and line.amount or 0.0), |
1734 | + 'debit': (order.payment_order_type == 'payment' |
1735 | + and line.amount or 0.0), |
1736 | + }) |
1737 | + reconcile_move_line_id = account_move_line_obj.create( |
1738 | + cr, uid, vals, context=context) |
1739 | + |
1740 | + # register the debit move line on the payment line |
1741 | + # and call reconciliation on it |
1742 | + payment_line_obj.write( |
1743 | + cr, uid, line.id, |
1744 | + {'transit_move_line_id': reconcile_move_line_id}, |
1745 | + context=context) |
1746 | + |
1747 | + payment_line_obj.debit_reconcile( |
1748 | + cr, uid, line.id, context=context) |
1749 | + account_move_obj.post(cr, uid, [move_id], context=context) |
1750 | + |
1751 | + # State field is written by act_sent_wait |
1752 | + self.write(cr, uid, ids, { |
1753 | + 'date_sent': fields.date.context_today( |
1754 | + self, cr, uid, context=context), |
1755 | + }, context=context) |
1756 | + |
1757 | + return True |
1758 | + |
1759 | + |
1760 | |
1761 | === modified file 'account_banking_payment/model/banking_import_transaction.py' |
1762 | --- account_banking_payment/model/banking_import_transaction.py 2013-06-03 09:47:11 +0000 |
1763 | +++ account_banking_payment/model/banking_import_transaction.py 2013-06-26 21:16:23 +0000 |
1764 | @@ -27,37 +27,44 @@ |
1765 | from openerp import netsvc |
1766 | from openerp.tools.translate import _ |
1767 | from openerp.addons.decimal_precision import decimal_precision as dp |
1768 | +from openerp.addons.account_banking.parsers.models import mem_bank_transaction as bt |
1769 | |
1770 | |
1771 | class banking_import_transaction(orm.Model): |
1772 | _inherit = 'banking.import.transaction' |
1773 | |
1774 | - def _match_debit_order( |
1775 | - self, cr, uid, trans, log, context=None): |
1776 | + def _match_payment_order( |
1777 | + self, cr, uid, trans, log, order_type='payment', context=None): |
1778 | |
1779 | - def is_zero(total): |
1780 | + def equals_order_amount(payment_order, transferred_amount): |
1781 | + if (not hasattr(payment_order, 'payment_order_type') |
1782 | + or payment_order.payment_order_type == 'payment'): |
1783 | + sign = 1 |
1784 | + else: |
1785 | + sign = -1 |
1786 | + total = payment_order.total + sign * transferred_amount |
1787 | return self.pool.get('res.currency').is_zero( |
1788 | - cr, uid, trans.statement_id.currency, total) |
1789 | + cr, uid, trans.statement_line_id.statement_id.currency, total) |
1790 | |
1791 | payment_order_obj = self.pool.get('payment.order') |
1792 | |
1793 | order_ids = payment_order_obj.search( |
1794 | - cr, uid, [('payment_order_type', '=', 'debit'), |
1795 | + cr, uid, [('payment_order_type', '=', order_type), |
1796 | ('state', '=', 'sent'), |
1797 | ('date_sent', '<=', trans.execution_date), |
1798 | ], |
1799 | limit=0, context=context) |
1800 | orders = payment_order_obj.browse(cr, uid, order_ids, context) |
1801 | candidates = [x for x in orders if |
1802 | - is_zero(x.total - trans.transferred_amount) and |
1803 | - x.line_ids and x.line_ids[0].debit_move_line_id] |
1804 | + equals_order_amount(x, trans.statement_line_id.amount)] |
1805 | if len(candidates) > 0: |
1806 | # retrieve the common account_id, if any |
1807 | account_id = False |
1808 | - for line in candidates[0].line_ids[0].debit_move_line_id.move_id.line_id: |
1809 | - if line.account_id.type == 'other': |
1810 | - account_id = line.account_id.id |
1811 | - break |
1812 | + if (candidates[0].line_ids[0].transit_move_line_id): |
1813 | + for line in candidates[0].line_ids[0].transit_move_line_id.move_id.line_id: |
1814 | + if line.account_id.type == 'other': |
1815 | + account_id = line.account_id.id |
1816 | + break |
1817 | return dict( |
1818 | move_line_ids = False, |
1819 | match_type = 'payment_order', |
1820 | @@ -82,7 +89,7 @@ |
1821 | # stornos MUST have an exact match |
1822 | if len(line_ids) == 1: |
1823 | account_id = payment_line_obj.get_storno_account_id( |
1824 | - cr, uid, line_ids[0], trans.transferred_amount, |
1825 | + cr, uid, line_ids[0], trans.statement_line_id.amount, |
1826 | trans.statement_id.currency, context=None) |
1827 | if account_id: |
1828 | return dict( |
1829 | @@ -114,7 +121,7 @@ |
1830 | x for x in payment_lines |
1831 | if x.communication == trans.reference |
1832 | and round(x.amount, digits) == -round( |
1833 | - trans.transferred_amount, digits) |
1834 | + trans.statement_line_id.amount, digits) |
1835 | and trans.remote_account in (x.bank_id.acc_number, |
1836 | x.bank_id.acc_number_domestic) |
1837 | ] |
1838 | @@ -171,10 +178,6 @@ |
1839 | raise orm.except_orm( |
1840 | _("Cannot reconcile"), |
1841 | _("Cannot reconcile: no direct debit order")) |
1842 | - if transaction.payment_order_id.payment_order_type != 'debit': |
1843 | - raise orm.except_orm( |
1844 | - _("Cannot reconcile"), |
1845 | - _("Reconcile payment order not implemented")) |
1846 | reconcile_id = payment_order_obj.debit_reconcile_transfer( |
1847 | cr, uid, |
1848 | transaction.payment_order_id.id, |
1849 | @@ -195,7 +198,6 @@ |
1850 | payment_line_obj = self.pool.get('payment.line') |
1851 | payment_line_obj.write( |
1852 | cr, uid, transaction.payment_line_id.id, { |
1853 | - 'export_state': 'done', |
1854 | 'date_done': transaction.statement_line_id.date, |
1855 | } |
1856 | ) |
1857 | @@ -232,11 +234,12 @@ |
1858 | if not transaction.payment_order_id: |
1859 | raise orm.except_orm( |
1860 | _("Cannot unreconcile"), |
1861 | - _("Cannot unreconcile: no direct debit order")) |
1862 | - if transaction.payment_order_id.payment_order_type != 'debit': |
1863 | + _("Cannot unreconcile: no payment or direct debit order")) |
1864 | + if not transaction.statement_line_id.reconcile_id: |
1865 | raise orm.except_orm( |
1866 | _("Cannot unreconcile"), |
1867 | - _("Unreconcile payment order not implemented")) |
1868 | + _("Payment orders without transfer move lines cannot be " |
1869 | + "unreconciled this way")) |
1870 | return payment_order_obj.debit_unreconcile_transfer( |
1871 | cr, uid, transaction.payment_order_id.id, |
1872 | transaction.statement_line_id.reconcile_id.id, |
1873 | @@ -302,17 +305,6 @@ |
1874 | cr, uid, transaction.payment_line_id.id, context) |
1875 | |
1876 | _columns = { |
1877 | - 'match_type': fields.selection( |
1878 | - # Add payment and storno types |
1879 | - [ |
1880 | - ('manual', 'Manual'), |
1881 | - ('move','Move'), |
1882 | - ('invoice', 'Invoice'), |
1883 | - ('payment', 'Payment'), |
1884 | - ('payment_order', 'Payment order'), |
1885 | - ('storno', 'Storno'), |
1886 | - ], |
1887 | - 'Match type'), |
1888 | 'payment_order_ids': fields.many2many( |
1889 | 'payment.order', 'banking_transaction_payment_order_rel', |
1890 | 'order_id', 'transaction_id', 'Payment orders'), |
1891 | @@ -334,14 +326,14 @@ |
1892 | return res |
1893 | |
1894 | def clear_and_write(self, cr, uid, ids, vals=None, context=None): |
1895 | - super(banking_import_transaction, self).clear_and_write( |
1896 | + write_vals = { |
1897 | + 'payment_line_id': False, |
1898 | + 'payment_order_id': False, |
1899 | + 'payment_order_ids': [(6, 0, [])], |
1900 | + } |
1901 | + write_vals.update(vals or {}) |
1902 | + return super(banking_import_transaction, self).clear_and_write( |
1903 | cr, uid, ids, vals=vals, context=context) |
1904 | - return self.write( |
1905 | - cr, uid, ids, { |
1906 | - 'payment_line_id': False, |
1907 | - 'payment_order_ids': [(6, 0, [])], |
1908 | - }, |
1909 | - context=context) |
1910 | |
1911 | def move_info2values(self, move_info): |
1912 | vals = super(banking_import_transaction, self).move_info2values( |
1913 | @@ -356,11 +348,25 @@ |
1914 | ) |
1915 | return vals |
1916 | |
1917 | - def match(self, cr, uid, ids, results=None, context=None): |
1918 | - res = super(banking_import_transaction, self).match( |
1919 | - cr, uid, ids, results=results, context=context) |
1920 | - |
1921 | - return res |
1922 | + def hook_match_payment(self, cr, uid, transaction, log, context=None): |
1923 | + """ |
1924 | + Called from match() in the core module. |
1925 | + Match payment batches, direct debit orders and stornos |
1926 | + """ |
1927 | + move_info = False |
1928 | + if transaction.type == bt.PAYMENT_BATCH: |
1929 | + move_info = self._match_payment_order( |
1930 | + cr, uid, transaction, log, |
1931 | + order_type='payment', context=context) |
1932 | + elif transaction.type == bt.DIRECT_DEBIT: |
1933 | + move_info = self._match_payment_order( |
1934 | + cr, uid, transaction, log, |
1935 | + order_type='debit', context=context) |
1936 | + elif transaction.type == bt.STORNO: |
1937 | + move_info = self._match_storno( |
1938 | + cr, uid, transaction, log, |
1939 | + context=context) |
1940 | + return move_info |
1941 | |
1942 | def __init__(self, pool, cr): |
1943 | """ |
1944 | @@ -369,14 +375,18 @@ |
1945 | """ |
1946 | super(banking_import_transaction, self).__init__(pool, cr) |
1947 | |
1948 | - banking_import_transaction.confirm_map.update({ |
1949 | + self.confirm_map.update({ |
1950 | 'storno': banking_import_transaction._confirm_storno, |
1951 | 'payment_order': banking_import_transaction._confirm_payment_order, |
1952 | 'payment': banking_import_transaction._confirm_payment, |
1953 | + 'payment_order_manual': banking_import_transaction._confirm_payment_order, |
1954 | + 'payment_manual': banking_import_transaction._confirm_payment, |
1955 | }) |
1956 | |
1957 | - banking_import_transaction.cancel_map.update({ |
1958 | + self.cancel_map.update({ |
1959 | 'storno': banking_import_transaction._cancel_storno, |
1960 | 'payment_order': banking_import_transaction._cancel_payment_order, |
1961 | 'payment': banking_import_transaction._cancel_payment, |
1962 | + 'payment_order_manual': banking_import_transaction._cancel_payment_order, |
1963 | + 'payment_manual': banking_import_transaction._cancel_payment, |
1964 | }) |
1965 | |
1966 | === modified file 'account_banking_payment/model/banking_transaction_wizard.py' |
1967 | --- account_banking_payment/model/banking_transaction_wizard.py 2013-03-17 09:10:15 +0000 |
1968 | +++ account_banking_payment/model/banking_transaction_wizard.py 2013-06-26 21:16:23 +0000 |
1969 | @@ -24,10 +24,59 @@ |
1970 | ############################################################################## |
1971 | |
1972 | from openerp.osv import orm, fields |
1973 | +from openerp.tools.translate import _ |
1974 | |
1975 | |
1976 | class banking_transaction_wizard(orm.TransientModel): |
1977 | _inherit = 'banking.transaction.wizard' |
1978 | + |
1979 | + def write(self, cr, uid, ids, vals, context=None): |
1980 | + """ |
1981 | + Check for manual payment orders or lines |
1982 | + """ |
1983 | + if not vals or not ids: |
1984 | + return True |
1985 | + manual_payment_order_id = vals.pop('manual_payment_order_id', False) |
1986 | + manual_payment_line_id = vals.pop('manual_payment_line_id', False) |
1987 | + res = super(banking_transaction_wizard, self).write( |
1988 | + cr, uid, ids, vals, context=context) |
1989 | + if manual_payment_order_id or manual_payment_line_id: |
1990 | + transaction_id = self.browse( |
1991 | + cr, uid, ids[0], |
1992 | + context=context).import_transaction_id |
1993 | + write_vals = {} |
1994 | + if manual_payment_order_id: |
1995 | + payment_order = self.pool.get('payment.order').browse( |
1996 | + cr, uid, manual_payment_order_id, |
1997 | + context=context) |
1998 | + if payment_order.payment_order_type == 'payment': |
1999 | + sign = 1 |
2000 | + else: |
2001 | + sign = -1 |
2002 | + total = (payment_order.total + sign * |
2003 | + transaction_id.statement_line_id.amount) |
2004 | + if not self.pool.get('res.currency').is_zero( |
2005 | + cr, uid, transaction_id.statement_line_id.statement_id.currency, total): |
2006 | + raise orm.except_orm( |
2007 | + _('Error'), |
2008 | + _('When matching a payment order, the amounts have to ' |
2009 | + 'match exactly')) |
2010 | + |
2011 | + if payment_order.mode and payment_order.mode.transfer_account_id: |
2012 | + transaction_id.statement_line_id.write({ |
2013 | + 'account_id': payment_order.mode.transfer_account_id.id, |
2014 | + }) |
2015 | + write_vals.update( |
2016 | + {'payment_order_id': manual_payment_order_id, |
2017 | + 'match_type': 'payment_order_manual'}) |
2018 | + else: |
2019 | + write_vals.update( |
2020 | + {'payment_line_id': manual_payment_line_id, |
2021 | + 'match_type': 'payment_manual'}) |
2022 | + self.pool.get('banking.import.transaction').clear_and_write( |
2023 | + cr, uid, transaction_id.id, write_vals, context=context) |
2024 | + return res |
2025 | + |
2026 | _columns = { |
2027 | 'payment_line_id': fields.related( |
2028 | 'import_transaction_id', 'payment_line_id', |
2029 | @@ -42,4 +91,13 @@ |
2030 | 'import_transaction_id', 'payment_order_id', |
2031 | string="Payment order to reconcile", |
2032 | type='many2one', relation='payment.order'), |
2033 | + 'manual_payment_order_id': fields.many2one( |
2034 | + 'payment.order', 'Match this payment order', |
2035 | + domain=[('state', '=', 'sent')]), |
2036 | + 'manual_payment_line_id': fields.many2one( |
2037 | + 'payment.line', 'Match this payment line', |
2038 | + domain=[ |
2039 | + ('order_id.state', '=', 'sent'), |
2040 | + ('date_done', '=', False), |
2041 | + ]), |
2042 | } |
2043 | |
2044 | === modified file 'account_banking_payment/model/payment_line.py' |
2045 | --- account_banking_payment/model/payment_line.py 2013-03-17 09:10:15 +0000 |
2046 | +++ account_banking_payment/model/payment_line.py 2013-06-26 21:16:23 +0000 |
2047 | @@ -24,11 +24,12 @@ |
2048 | ############################################################################## |
2049 | |
2050 | from openerp.osv import orm, fields |
2051 | - |
2052 | +from openerp import netsvc |
2053 | +from openerp.tools.translate import _ |
2054 | |
2055 | class payment_line(orm.Model): |
2056 | ''' |
2057 | - Add extra export_state and date_done fields; make destination bank account |
2058 | + Add some fields; make destination bank account |
2059 | mandatory, as it makes no sense to send payments into thin air. |
2060 | Edit: Payments can be by cash too, which is prohibited by mandatory bank |
2061 | accounts. |
2062 | @@ -36,146 +37,34 @@ |
2063 | _inherit = 'payment.line' |
2064 | _columns = { |
2065 | # New fields |
2066 | - 'export_state': fields.selection([ |
2067 | - ('draft', 'Draft'), |
2068 | - ('open','Confirmed'), |
2069 | - ('cancel','Cancelled'), |
2070 | - ('sent', 'Sent'), |
2071 | - ('rejected', 'Rejected'), |
2072 | - ('done','Done'), |
2073 | - ], 'State', select=True |
2074 | - ), |
2075 | 'msg': fields.char('Message', size=255, required=False, readonly=True), |
2076 | - |
2077 | - # Redefined fields: added states |
2078 | - 'date_done': fields.datetime('Date Confirmed', select=True, |
2079 | - readonly=True), |
2080 | - 'name': fields.char( |
2081 | - 'Your Reference', size=64, required=True, |
2082 | - states={ |
2083 | - 'sent': [('readonly', True)], |
2084 | - 'rejected': [('readonly', True)], |
2085 | - 'done': [('readonly', True)] |
2086 | - }, |
2087 | - ), |
2088 | + 'date_done': fields.date( |
2089 | + 'Date Confirmed', select=True, readonly=True), |
2090 | + # Communication: required is dependend on the mode |
2091 | 'communication': fields.char( |
2092 | 'Communication', size=64, required=False, |
2093 | help=("Used as the message between ordering customer and current " |
2094 | "company. Depicts 'What do you want to say to the recipient" |
2095 | " about this order ?'" |
2096 | ), |
2097 | - states={ |
2098 | - 'sent': [('readonly', True)], |
2099 | - 'rejected': [('readonly', True)], |
2100 | - 'done': [('readonly', True)] |
2101 | - }, |
2102 | ), |
2103 | + # Communication2: enlarge to 128 |
2104 | 'communication2': fields.char( |
2105 | 'Communication 2', size=128, |
2106 | help='The successor message of Communication.', |
2107 | - states={ |
2108 | - 'sent': [('readonly', True)], |
2109 | - 'rejected': [('readonly', True)], |
2110 | - 'done': [('readonly', True)] |
2111 | - }, |
2112 | - ), |
2113 | - 'move_line_id': fields.many2one( |
2114 | - 'account.move.line', 'Entry line', |
2115 | - domain=[('reconcile_id','=', False), |
2116 | - ('account_id.type', '=','payable') |
2117 | - ], |
2118 | - help=('This Entry Line will be referred for the information of ' |
2119 | - 'the ordering customer.' |
2120 | - ), |
2121 | - states={ |
2122 | - 'sent': [('readonly', True)], |
2123 | - 'rejected': [('readonly', True)], |
2124 | - 'done': [('readonly', True)] |
2125 | - }, |
2126 | - ), |
2127 | - 'amount_currency': fields.float( |
2128 | - 'Amount in Partner Currency', digits=(16,2), |
2129 | - required=True, |
2130 | - help='Payment amount in the partner currency', |
2131 | - states={ |
2132 | - 'sent': [('readonly', True)], |
2133 | - 'rejected': [('readonly', True)], |
2134 | - 'done': [('readonly', True)] |
2135 | - }, |
2136 | - ), |
2137 | - 'currency': fields.many2one( |
2138 | - 'res.currency', 'Partner Currency', required=True, |
2139 | - states={ |
2140 | - 'sent': [('readonly', True)], |
2141 | - 'rejected': [('readonly', True)], |
2142 | - 'done': [('readonly', True)] |
2143 | - }, |
2144 | - ), |
2145 | - 'bank_id': fields.many2one( |
2146 | - 'res.partner.bank', 'Destination Bank account', |
2147 | - states={ |
2148 | - 'sent': [('readonly', True)], |
2149 | - 'rejected': [('readonly', True)], |
2150 | - 'done': [('readonly', True)] |
2151 | - }, |
2152 | - ), |
2153 | - 'order_id': fields.many2one( |
2154 | - 'payment.order', 'Order', required=True, |
2155 | - ondelete='cascade', select=True, |
2156 | - states={ |
2157 | - 'sent': [('readonly', True)], |
2158 | - 'rejected': [('readonly', True)], |
2159 | - 'done': [('readonly', True)] |
2160 | - }, |
2161 | - ), |
2162 | - 'partner_id': fields.many2one( |
2163 | - 'res.partner', string="Partner", required=True, |
2164 | - help='The Ordering Customer', |
2165 | - states={ |
2166 | - 'sent': [('readonly', True)], |
2167 | - 'rejected': [('readonly', True)], |
2168 | - 'done': [('readonly', True)] |
2169 | - }, |
2170 | - ), |
2171 | - 'date': fields.date( |
2172 | - 'Payment Date', |
2173 | - help=("If no payment date is specified, the bank will treat this " |
2174 | - "payment line directly" |
2175 | - ), |
2176 | - states={ |
2177 | - 'sent': [('readonly', True)], |
2178 | - 'rejected': [('readonly', True)], |
2179 | - 'done': [('readonly', True)] |
2180 | - }, |
2181 | - ), |
2182 | - 'state': fields.selection([ |
2183 | - ('normal','Free'), |
2184 | - ('structured','Structured') |
2185 | - ], 'Communication Type', required=True, |
2186 | - states={ |
2187 | - 'sent': [('readonly', True)], |
2188 | - 'rejected': [('readonly', True)], |
2189 | - 'done': [('readonly', True)] |
2190 | - }, |
2191 | - ), |
2192 | - } |
2193 | + ), |
2194 | + 'transit_move_line_id': fields.many2one( |
2195 | + # this line is part of the credit side of move 2a |
2196 | + # from the documentation |
2197 | + 'account.move.line', 'Debit move line', |
2198 | + readonly=True, |
2199 | + help="Move line through which the debit order pays the invoice", |
2200 | + ), |
2201 | + } |
2202 | + |
2203 | _defaults = { |
2204 | - 'export_state': 'draft', |
2205 | - 'date_done': False, |
2206 | 'msg': '', |
2207 | - } |
2208 | - |
2209 | - def fields_get(self, cr, uid, fields=None, context=None): |
2210 | - res = super(payment_line, self).fields_get(cr, uid, fields, context) |
2211 | - if 'communication' in res: |
2212 | - res['communication'].setdefault('states', {}) |
2213 | - res['communication']['states']['structured'] = [('required', True)] |
2214 | - if 'communication2' in res: |
2215 | - res['communication2'].setdefault('states', {}) |
2216 | - res['communication2']['states']['structured'] = [('readonly', True)] |
2217 | - res['communication2']['states']['normal'] = [('readonly', False)] |
2218 | - |
2219 | - return res |
2220 | + } |
2221 | |
2222 | """ |
2223 | Hooks for processing direct debit orders, such as implemented in |
2224 | @@ -216,3 +105,76 @@ |
2225 | """ |
2226 | |
2227 | return False |
2228 | + |
2229 | + def debit_reconcile(self, cr, uid, payment_line_id, context=None): |
2230 | + """ |
2231 | + Reconcile a debit order's payment line with the the move line |
2232 | + that it is based on. Called from payment_order.action_sent(). |
2233 | + As the amount is derived directly from the counterpart move line, |
2234 | + we do not expect a write off. Take partially reconcilions into |
2235 | + account though. |
2236 | + |
2237 | + :param payment_line_id: the single id of the canceled payment line |
2238 | + """ |
2239 | + |
2240 | + if isinstance(payment_line_id, (list, tuple)): |
2241 | + payment_line_id = payment_line_id[0] |
2242 | + reconcile_obj = self.pool.get('account.move.reconcile') |
2243 | + move_line_obj = self.pool.get('account.move.line') |
2244 | + payment_line = self.browse(cr, uid, payment_line_id, context=context) |
2245 | + |
2246 | + transit_move_line = payment_line.transit_move_line_id |
2247 | + torec_move_line = payment_line.move_line_id |
2248 | + |
2249 | + if (not transit_move_line or not torec_move_line): |
2250 | + raise orm.except_orm( |
2251 | + _('Can not reconcile'), |
2252 | + _('No move line for line %s') % payment_line.name) |
2253 | + if torec_move_line.reconcile_id: # torec_move_line.reconcile_partial_id: |
2254 | + raise orm.except_orm( |
2255 | + _('Error'), |
2256 | + _('Move line %s has already been reconciled') % |
2257 | + torec_move_line.name |
2258 | + ) |
2259 | + if transit_move_line.reconcile_id or transit_move_line.reconcile_partial_id: |
2260 | + raise orm.except_orm( |
2261 | + _('Error'), |
2262 | + _('Move line %s has already been reconciled') % |
2263 | + transit_move_line.name |
2264 | + ) |
2265 | + |
2266 | + def is_zero(total): |
2267 | + return self.pool.get('res.currency').is_zero( |
2268 | + cr, uid, transit_move_line.company_id.currency_id, total) |
2269 | + |
2270 | + line_ids = [transit_move_line.id, torec_move_line.id] |
2271 | + if torec_move_line.reconcile_partial_id: |
2272 | + line_ids = [ |
2273 | + x.id for x in |
2274 | + transit_move_line.reconcile_partial_id.line_partial_ids |
2275 | + ] + [torec_move_line.id] |
2276 | + |
2277 | + total = move_line_obj.get_balance(cr, uid, line_ids) |
2278 | + vals = { |
2279 | + 'type': 'auto', |
2280 | + 'line_id': is_zero(total) and [(6, 0, line_ids)] or [(6, 0, [])], |
2281 | + 'line_partial_ids': is_zero(total) and [(6, 0, [])] or [(6, 0, line_ids)], |
2282 | + } |
2283 | + |
2284 | + if torec_move_line.reconcile_partial_id: |
2285 | + reconcile_obj.write( |
2286 | + cr, uid, transit_move_line.reconcile_partial_id.id, |
2287 | + vals, context=context) |
2288 | + else: |
2289 | + reconcile_obj.create( |
2290 | + cr, uid, vals, context=context) |
2291 | + for line_id in line_ids: |
2292 | + netsvc.LocalService("workflow").trg_trigger( |
2293 | + uid, 'account.move.line', line_id, cr) |
2294 | + |
2295 | + # If a bank transaction of a storno was first confirmed |
2296 | + # and now canceled (the invoice is now in state 'debit_denied' |
2297 | + if torec_move_line.invoice: |
2298 | + netsvc.LocalService("workflow").trg_validate( |
2299 | + uid, 'account.invoice', torec_move_line.invoice.id, |
2300 | + 'undo_debit_denied', cr) |
2301 | |
2302 | === modified file 'account_banking_payment/model/payment_mode.py' |
2303 | --- account_banking_payment/model/payment_mode.py 2013-03-17 09:10:15 +0000 |
2304 | +++ account_banking_payment/model/payment_mode.py 2013-06-26 21:16:23 +0000 |
2305 | @@ -46,6 +46,27 @@ |
2306 | _columns = { |
2307 | 'type': fields.many2one( |
2308 | 'payment.mode.type', 'Payment type', |
2309 | + required=True, |
2310 | help='Select the Payment Type for the Payment Mode.' |
2311 | ), |
2312 | + 'transfer_account_id': fields.many2one( |
2313 | + 'account.account', 'Transfer account', |
2314 | + domain=[('type', '=', 'other'), |
2315 | + ('reconcile', '=', True)], |
2316 | + help=('Pay off lines in sent orders with a ' |
2317 | + 'move on this account. For debit type modes only. ' |
2318 | + 'You can only select accounts of type regular that ' |
2319 | + 'are marked for reconciliation'), |
2320 | + ), |
2321 | + 'transfer_journal_id': fields.many2one( |
2322 | + 'account.journal', 'Transfer journal', |
2323 | + help=('Journal to write payment entries when confirming ' |
2324 | + 'a debit order of this mode'), |
2325 | + ), |
2326 | + 'payment_term_ids': fields.many2many( |
2327 | + 'account.payment.term', 'account_payment_order_terms_rel', |
2328 | + 'mode_id', 'term_id', 'Payment terms', |
2329 | + help=('Limit selected invoices to invoices with these payment ' |
2330 | + 'terms') |
2331 | + ), |
2332 | } |
2333 | |
2334 | === modified file 'account_banking_payment/model/payment_order_create.py' |
2335 | --- account_banking_payment/model/payment_order_create.py 2013-06-04 21:19:18 +0000 |
2336 | +++ account_banking_payment/model/payment_order_create.py 2013-06-26 21:16:23 +0000 |
2337 | @@ -26,11 +26,77 @@ |
2338 | from datetime import datetime |
2339 | from openerp.osv import orm, fields |
2340 | from openerp.tools import DEFAULT_SERVER_DATE_FORMAT |
2341 | +from openerp.tools.translate import _ |
2342 | |
2343 | |
2344 | class payment_order_create(orm.TransientModel): |
2345 | _inherit = 'payment.order.create' |
2346 | |
2347 | + def extend_payment_order_domain( |
2348 | + self, cr, uid, payment_order, domain, context=None): |
2349 | + if payment_order.payment_order_type == 'payment': |
2350 | + domain += [ |
2351 | + ('account_id.type', '=', 'payable'), |
2352 | + ('amount_to_pay', '>', 0) |
2353 | + ] |
2354 | + return True |
2355 | + |
2356 | + def search_entries(self, cr, uid, ids, context=None): |
2357 | + """ |
2358 | + This method taken from account_payment module. |
2359 | + We adapt the domain based on the payment_order_type |
2360 | + """ |
2361 | + line_obj = self.pool.get('account.move.line') |
2362 | + mod_obj = self.pool.get('ir.model.data') |
2363 | + if context is None: |
2364 | + context = {} |
2365 | + data = self.read(cr, uid, ids, ['duedate'], context=context)[0] |
2366 | + search_due_date = data['duedate'] |
2367 | + |
2368 | + ### start account_banking_payment ### |
2369 | + payment = self.pool.get('payment.order').browse( |
2370 | + cr, uid, context['active_id'], context=context) |
2371 | + # Search for move line to pay: |
2372 | + domain = [ |
2373 | + ('move_id.state', '=', 'posted'), |
2374 | + ('reconcile_id', '=', False), |
2375 | + ('company_id', '=', payment.mode.company_id.id), |
2376 | + ] |
2377 | + # apply payment term filter |
2378 | + if payment.mode.payment_term_ids: |
2379 | + domain += [ |
2380 | + ('invoice.payment_term', 'in', |
2381 | + [term.id for term in payment.mode.payment_term_ids] |
2382 | + ) |
2383 | + ] |
2384 | + self.extend_payment_order_domain( |
2385 | + cr, uid, payment, domain, context=context) |
2386 | + ### end account_direct_debit ### |
2387 | + |
2388 | + domain = domain + [ |
2389 | + '|', ('date_maturity', '<=', search_due_date), |
2390 | + ('date_maturity', '=', False) |
2391 | + ] |
2392 | + line_ids = line_obj.search(cr, uid, domain, context=context) |
2393 | + context.update({'line_ids': line_ids}) |
2394 | + model_data_ids = mod_obj.search( |
2395 | + cr, uid,[ |
2396 | + ('model', '=', 'ir.ui.view'), |
2397 | + ('name', '=', 'view_create_payment_order_lines')], |
2398 | + context=context) |
2399 | + resource_id = mod_obj.read( |
2400 | + cr, uid, model_data_ids, fields=['res_id'], |
2401 | + context=context)[0]['res_id'] |
2402 | + return {'name': _('Entry Lines'), |
2403 | + 'context': context, |
2404 | + 'view_type': 'form', |
2405 | + 'view_mode': 'form', |
2406 | + 'res_model': 'payment.order.create', |
2407 | + 'views': [(resource_id, 'form')], |
2408 | + 'type': 'ir.actions.act_window', |
2409 | + 'target': 'new', |
2410 | + } |
2411 | + |
2412 | def create_payment(self, cr, uid, ids, context=None): |
2413 | ''' |
2414 | This method is a slightly modified version of the existing method on this |
2415 | @@ -51,7 +117,8 @@ |
2416 | if not line_ids: |
2417 | return {'type': 'ir.actions.act_window_close'} |
2418 | |
2419 | - payment = order_obj.browse(cr, uid, context['active_id'], context=context) |
2420 | + payment = order_obj.browse( |
2421 | + cr, uid, context['active_id'], context=context) |
2422 | ### account banking |
2423 | # t = None |
2424 | # line2bank = line_obj.line2bank(cr, uid, line_ids, t, context) |
2425 | @@ -75,10 +142,10 @@ |
2426 | ### end account banking |
2427 | elif payment.date_prefered == 'fixed': |
2428 | ### account_banking |
2429 | - # date_to_pay = payment.date_planned |
2430 | + # date_to_pay = payment.date_scheduled |
2431 | date_to_pay = ( |
2432 | - payment.date_planned |
2433 | - if payment.date_planned and payment.date_planned > _today |
2434 | + payment.date_scheduled |
2435 | + if payment.date_scheduled and payment.date_scheduled > _today |
2436 | else False) |
2437 | ### end account banking |
2438 | |
2439 | @@ -125,6 +192,8 @@ |
2440 | 'state': state, |
2441 | ### end account banking |
2442 | 'date': date_to_pay, |
2443 | - 'currency': line.invoice and line.invoice.currency_id.id or line.journal_id.currency.id or line.journal_id.company_id.currency_id.id, |
2444 | + 'currency': (line.invoice and line.invoice.currency_id.id |
2445 | + or line.journal_id.currency.id |
2446 | + or line.journal_id.company_id.currency_id.id), |
2447 | }, context=context) |
2448 | return {'type': 'ir.actions.act_window_close'} |
2449 | |
2450 | === modified file 'account_banking_payment/view/account_payment.xml' |
2451 | --- account_banking_payment/view/account_payment.xml 2013-05-01 14:40:54 +0000 |
2452 | +++ account_banking_payment/view/account_payment.xml 2013-06-26 21:16:23 +0000 |
2453 | @@ -9,33 +9,28 @@ |
2454 | <field name="name">account.payment.order.form.banking-1</field> |
2455 | <field name="inherit_id" ref="account_payment.view_payment_order_form" /> |
2456 | <field name="model">payment.order</field> |
2457 | - <field name="type">form</field> |
2458 | <field name="arch" type="xml"> |
2459 | <data> |
2460 | - <xpath expr="/form/group/button[@string='Select Invoices to Pay']" |
2461 | - position="attributes"> |
2462 | - <attribute name="attrs">{'invisible':[('state','!=','draft')]}</attribute> |
2463 | - </xpath> |
2464 | - <xpath expr="/form/group/button[@string='Make Payments']" |
2465 | - position="replace"> |
2466 | - <button name="launch_wizard" states="open" string="Make Payments" type="object" icon="gtk-execute"/> |
2467 | - <newline/> |
2468 | + <xpath expr="//button[@string='Select Invoices to Pay']" |
2469 | + position="attributes"> |
2470 | + <attribute name="attrs">{ |
2471 | + 'invisible':[('state','!=','draft')] |
2472 | + }</attribute> |
2473 | + </xpath> |
2474 | + <xpath expr="//button[@string='Make Payments']" |
2475 | + position="attributes"> |
2476 | + <attribute name="name">launch_wizard</attribute> |
2477 | + </xpath> |
2478 | + <!-- Communication only used for 'structured' communication --> |
2479 | + <xpath expr="//field[@name='line_ids']/form//field[@name='communication']" |
2480 | + position="attributes"> |
2481 | + <attribute name="attrs">{ |
2482 | + 'readonly': [('state', '=', 'normal')] |
2483 | + }</attribute> |
2484 | </xpath> |
2485 | </data> |
2486 | </field> |
2487 | </record> |
2488 | |
2489 | - <record id="view_banking_payment_order_tree_1" model="ir.ui.view"> |
2490 | - <field name="name">account.payment.order.tree.banking-1</field> |
2491 | - <field name="inherit_id" ref="account_payment.view_payment_order_tree" /> |
2492 | - <field name="model">payment.order</field> |
2493 | - <field name="type">tree</field> |
2494 | - <field name="arch" type="xml"> |
2495 | - <button string="Make Payments" position="replace"> |
2496 | - <button name="launch_wizard" states="open" string="Make Payments" type="object" icon="gtk-execute"/> |
2497 | - </button> |
2498 | - </field> |
2499 | - </record> |
2500 | - |
2501 | </data> |
2502 | </openerp> |
2503 | |
2504 | === modified file 'account_banking_payment/view/bank_payment_manual.xml' |
2505 | --- account_banking_payment/view/bank_payment_manual.xml 2013-03-17 20:04:17 +0000 |
2506 | +++ account_banking_payment/view/bank_payment_manual.xml 2013-06-26 21:16:23 +0000 |
2507 | @@ -4,9 +4,8 @@ |
2508 | <record id="view_payment_manual_form" model="ir.ui.view"> |
2509 | <field name="name">Form for manual payment wizard</field> |
2510 | <field name="model">payment.manual</field> |
2511 | - <field name="type">form</field> |
2512 | <field name="arch" type="xml"> |
2513 | - <form> |
2514 | + <form string="Manual payment"> |
2515 | <label string="Payment order(s) have been set to 'sent'"/> |
2516 | <button special="cancel" icon="gtk-ok" string="OK"/> |
2517 | </form> |
2518 | |
2519 | === modified file 'account_banking_payment/view/banking_transaction_wizard.xml' |
2520 | --- account_banking_payment/view/banking_transaction_wizard.xml 2013-03-17 20:04:17 +0000 |
2521 | +++ account_banking_payment/view/banking_transaction_wizard.xml 2013-06-26 21:16:23 +0000 |
2522 | @@ -6,7 +6,6 @@ |
2523 | <field name="model">banking.transaction.wizard</field> |
2524 | <field name="inherit_id" |
2525 | ref="account_banking.transaction_wizard_first" /> |
2526 | - <field name="type">form</field> |
2527 | <field name="arch" type="xml"> |
2528 | <field name="invoice_ids" position="before"> |
2529 | <field name="payment_order_ids" invisible="True"/> |
2530 | @@ -14,20 +13,23 @@ |
2531 | <xpath expr="//group/separator[@string='Multiple matches']/.." |
2532 | position="after"> |
2533 | <field name='payment_line_id' |
2534 | - attrs="{'invisible': [ |
2535 | - ('match_type', '!=', 'storno'), |
2536 | - ('match_type', '!=', 'payment')] |
2537 | - }" /> |
2538 | + attrs="{'invisible': [('match_type', 'not in', |
2539 | + ('storno', 'payment', 'payment_manual'))]}" |
2540 | + /> |
2541 | </xpath> |
2542 | <field name="move_line_id" position="after"> |
2543 | <field name='payment_order_id' |
2544 | - attrs="{'readonly': [ |
2545 | - ('match_multi', '=', False)], |
2546 | - 'invisible': [ |
2547 | - ('match_type', '!=', 'payment_order')]}" |
2548 | + attrs="{'readonly': [('match_multi', '=', False)], |
2549 | + 'invisible': [('match_type', 'not in', |
2550 | + ('payment_order', 'payment_order_manual'))] |
2551 | + }" |
2552 | domain="[('id', 'in', payment_order_ids[0][2])]" |
2553 | /> |
2554 | </field> |
2555 | + <field name="manual_move_line_id" position="after"> |
2556 | + <field name="manual_payment_line_id"/> |
2557 | + <field name="manual_payment_order_id"/> |
2558 | + </field> |
2559 | </field> |
2560 | </record> |
2561 | </data> |
2562 | |
2563 | === added file 'account_banking_payment/view/payment_mode.xml' |
2564 | --- account_banking_payment/view/payment_mode.xml 1970-01-01 00:00:00 +0000 |
2565 | +++ account_banking_payment/view/payment_mode.xml 2013-06-26 21:16:23 +0000 |
2566 | @@ -0,0 +1,43 @@ |
2567 | +<?xml version="1.0" encoding="utf-8"?> |
2568 | +<openerp> |
2569 | + <data> |
2570 | + |
2571 | + <!-- |
2572 | + Add the payment mode type and transfer settings |
2573 | + --> |
2574 | + <record id="view_payment_mode_form_inherit" model="ir.ui.view"> |
2575 | + <field name="name">payment.mode.form.inherit</field> |
2576 | + <field name="model">payment.mode</field> |
2577 | + <field name="inherit_id" ref="account_payment.view_payment_mode_form"/> |
2578 | + <field name="arch" type="xml"> |
2579 | + <field name="company_id" position="after"> |
2580 | + <field name="type"/> |
2581 | + <group colspan="4" col="4"> |
2582 | + <group colspan="2"> |
2583 | + <separator colspan="2" |
2584 | + string="Transfer move settings" /> |
2585 | + <field name="transfer_account_id" |
2586 | + domain="[('type', '=', 'other'), |
2587 | + ('reconcile', '=', True), |
2588 | + ('company_id', '=', company_id)]" |
2589 | + context="{ |
2590 | + 'default_type': 'other', |
2591 | + 'default_reconcile': True, |
2592 | + 'default_company_id': company_id}" |
2593 | + /> |
2594 | + <field name="transfer_journal_id" |
2595 | + domain="[('company_id', '=', company_id)]" |
2596 | + /> |
2597 | + </group> |
2598 | + <group colspan="2"> |
2599 | + <separator colspan="2" |
2600 | + string="Optional filter by payment term" /> |
2601 | + <field name="payment_term_ids" nolabel="1" colspan="2"/> |
2602 | + </group> |
2603 | + </group> |
2604 | + </field> |
2605 | + </field> |
2606 | + </record> |
2607 | + |
2608 | + </data> |
2609 | +</openerp> |
2610 | |
2611 | === modified file 'account_banking_payment/view/payment_mode_type.xml' |
2612 | --- account_banking_payment/view/payment_mode_type.xml 2013-03-16 16:44:19 +0000 |
2613 | +++ account_banking_payment/view/payment_mode_type.xml 2013-06-26 21:16:23 +0000 |
2614 | @@ -2,24 +2,10 @@ |
2615 | <openerp> |
2616 | <data> |
2617 | |
2618 | - <!-- Add the payment mode type to the payment mode views --> |
2619 | - <record id="view_payment_mode_form_inherit" model="ir.ui.view"> |
2620 | - <field name="name">payment.mode.form.inherit</field> |
2621 | - <field name="model">payment.mode</field> |
2622 | - <field name="inherit_id" ref="account_payment.view_payment_mode_form"/> |
2623 | - <field name="type">form</field> |
2624 | - <field name="arch" type="xml"> |
2625 | - <field name="company_id" position="after"> |
2626 | - <field name="type"/> |
2627 | - </field> |
2628 | - </field> |
2629 | - </record> |
2630 | - |
2631 | <record id="view_payment_mode_tree_inherit" model="ir.ui.view"> |
2632 | <field name="name">payment.mode.tree.inherit</field> |
2633 | <field name="model">payment.mode</field> |
2634 | <field name="inherit_id" ref="account_payment.view_payment_mode_tree"/> |
2635 | - <field name="type">tree</field> |
2636 | <field name="arch" type="xml"> |
2637 | <field name="company_id" position="after"> |
2638 | <field name="type"/> |
2639 | @@ -31,9 +17,8 @@ |
2640 | <record model="ir.ui.view" id="view_payment_mode_type_form"> |
2641 | <field name="name">view.payment.mode.type.form</field> |
2642 | <field name="model">payment.mode.type</field> |
2643 | - <field name="type">form</field> |
2644 | <field name="arch" type="xml"> |
2645 | - <form> |
2646 | + <form string="Payment mode"> |
2647 | <field name="name" /> |
2648 | <field name="code" /> |
2649 | <field name="suitable_bank_types"/> |
2650 | |
2651 | === modified file 'account_banking_payment/workflow/account_payment.xml' |
2652 | --- account_banking_payment/workflow/account_payment.xml 2013-03-16 16:44:19 +0000 |
2653 | +++ account_banking_payment/workflow/account_payment.xml 2013-06-26 21:16:23 +0000 |
2654 | @@ -8,6 +8,13 @@ |
2655 | <field name="action">action_sent()</field> |
2656 | <field name="kind">function</field> |
2657 | </record> |
2658 | + <!-- New activity for workflow payment order: sent --> |
2659 | + <record id="account_banking.act_sent_wait" model="workflow.activity"> |
2660 | + <field name="name">sent_wait</field> |
2661 | + <field name="wkf_id" ref="account_payment.wkf_payment_order"/> |
2662 | + <field name="action">write({'state': 'sent'})</field> |
2663 | + <field name="kind">function</field> |
2664 | + </record> |
2665 | <!-- New activity for workflow payment order: rejected --> |
2666 | <record id="account_banking.act_rejected" model="workflow.activity"> |
2667 | <field name="name">rejected</field> |
2668 | @@ -16,23 +23,47 @@ |
2669 | write({'state':'rejected'})</field> |
2670 | <field name="kind">function</field> |
2671 | </record> |
2672 | - <!-- Add new transition sent -> done --> |
2673 | + <!-- Rewrite existing open -> done transition to include 'sent' stage --> |
2674 | + <record id="account_payment.trans_open_done" model="workflow.transition"> |
2675 | + <field name="act_from" ref="account_payment.act_open"/> |
2676 | + <field name="act_to" ref="account_banking.act_sent"/> |
2677 | + <field name="signal">sent</field> |
2678 | + </record> |
2679 | + <!-- From sent straight to sent_wait --> |
2680 | + <record id="account_banking.trans_sent_sent_wait" model="workflow.transition"> |
2681 | + <field name="act_from" ref="account_banking.act_sent"/> |
2682 | + <field name="act_to" ref="account_banking.act_sent_wait"/> |
2683 | + </record> |
2684 | + <!-- Reconciliation from the banking statement leads to done state --> |
2685 | <record id="account_banking.trans_sent_done" model="workflow.transition"> |
2686 | - <field name="act_from" ref="account_banking.act_sent"/> |
2687 | + <field name="act_from" ref="account_banking.act_sent_wait"/> |
2688 | <field name="act_to" ref="account_payment.act_done"/> |
2689 | <field name="signal">done</field> |
2690 | </record> |
2691 | - <!-- Add new transition sent -> rejected --> |
2692 | + <!-- Rejected by the bank --> |
2693 | <record id="account_banking.trans_sent_rejected" model="workflow.transition"> |
2694 | <field name="act_from" ref="account_banking.act_sent"/> |
2695 | <field name="act_to" ref="account_banking.act_rejected"/> |
2696 | <field name="signal">rejected</field> |
2697 | </record> |
2698 | - <!-- Rewrite existing open -> done transition to include 'sent' --> |
2699 | - <record id="account_payment.trans_open_done" model="workflow.transition"> |
2700 | - <field name="act_from" ref="account_payment.act_open"/> |
2701 | - <field name="act_to" ref="account_banking.act_sent"/> |
2702 | - <field name="signal">sent</field> |
2703 | - </record> |
2704 | + <!-- |
2705 | + Transition to undo the payment order and reset to |
2706 | + sent, triggered by cancelling a bank transaction |
2707 | + with which the order was reconciled. |
2708 | + For this, we need to cancel the flow stop on the done state, |
2709 | + unfortunately. |
2710 | + --> |
2711 | + <record id="account_payment.act_done" model="workflow.activity"> |
2712 | + <field name="flow_stop" eval="False"/> |
2713 | + </record> |
2714 | + |
2715 | + <!-- Cancel the reconciled payment order --> |
2716 | + <record id="trans_done_sent" model="workflow.transition"> |
2717 | + <field name="act_from" ref="account_payment.act_done"/> |
2718 | + <field name="act_to" ref="account_banking.act_sent_wait"/> |
2719 | + <field name="condition">test_undo_done()</field> |
2720 | + <field name="signal">undo_done</field> |
2721 | + </record> |
2722 | + |
2723 | </data> |
2724 | </openerp> |
2725 | |
2726 | === modified file 'account_banking_uk_hsbc/__openerp__.py' |
2727 | --- account_banking_uk_hsbc/__openerp__.py 2013-04-15 14:14:27 +0000 |
2728 | +++ account_banking_uk_hsbc/__openerp__.py 2013-06-26 21:16:23 +0000 |
2729 | @@ -25,7 +25,7 @@ |
2730 | 'author': 'credativ Ltd', |
2731 | 'website': 'http://www.credativ.co.uk', |
2732 | 'category': 'Account Banking', |
2733 | - 'depends': ['account_banking'], |
2734 | + 'depends': ['account_banking_payment'], |
2735 | 'data': [ |
2736 | 'account_banking_uk_hsbc.xml', |
2737 | 'hsbc_clientid_view.xml', |
2738 | |
2739 | === modified file 'account_direct_debit/__openerp__.py' |
2740 | --- account_direct_debit/__openerp__.py 2013-04-15 14:14:27 +0000 |
2741 | +++ account_direct_debit/__openerp__.py 2013-06-26 21:16:23 +0000 |
2742 | @@ -1,6 +1,6 @@ |
2743 | ############################################################################## |
2744 | # |
2745 | -# Copyright (C) 2011 Therp BV (<http://therp.nl>). |
2746 | +# Copyright (C) 2011 - 2013 Therp BV (<http://therp.nl>). |
2747 | # Copyright (C) 2011 Smile (<http://smile.fr>). |
2748 | # All Rights Reserved |
2749 | # |
2750 | @@ -20,9 +20,9 @@ |
2751 | ############################################################################## |
2752 | { |
2753 | 'name': 'Direct Debit', |
2754 | - 'version': '6.1.1.134', |
2755 | + 'version': '7.0.2.134', |
2756 | 'license': 'AGPL-3', |
2757 | - 'author': 'Therp BV / Smile', |
2758 | + 'author': ['Therp BV', 'Smile'], |
2759 | 'website': 'https://launchpad.net/banking-addons', |
2760 | 'category': 'Banking addons', |
2761 | 'depends': ['account_banking'], |
2762 | @@ -30,7 +30,6 @@ |
2763 | 'view/account_payment.xml', |
2764 | 'view/account_invoice.xml', |
2765 | 'workflow/account_invoice.xml', |
2766 | - 'workflow/account_payment.xml', |
2767 | 'data/account_payment_term.xml', |
2768 | ], |
2769 | 'description': ''' |
2770 | @@ -49,5 +48,5 @@ |
2771 | banking institutions. The banking addons are a continuation of Account Banking |
2772 | Framework by Edusense BV. See https://launchpad.net/banking-addons. |
2773 | ''', |
2774 | - 'installable': False, |
2775 | + 'installable': True, |
2776 | } |
2777 | |
2778 | === modified file 'account_direct_debit/i18n/nl.po' |
2779 | --- account_direct_debit/i18n/nl.po 2012-08-08 10:32:52 +0000 |
2780 | +++ account_direct_debit/i18n/nl.po 2013-06-26 21:16:23 +0000 |
2781 | @@ -175,7 +175,7 @@ |
2782 | msgstr "De betaalregelnaam moet uniek zijn!" |
2783 | |
2784 | #. module: account_direct_debit |
2785 | -#: field:payment.line,debit_move_line_id:0 |
2786 | +#: field:payment.line,transit_move_line_id:0 |
2787 | msgid "Debit move line" |
2788 | msgstr "Debetboeking" |
2789 | |
2790 | @@ -200,7 +200,7 @@ |
2791 | msgstr "Factuur" |
2792 | |
2793 | #. module: account_direct_debit |
2794 | -#: help:payment.line,debit_move_line_id:0 |
2795 | +#: help:payment.line,transit_move_line_id:0 |
2796 | msgid "Move line through which the debit order pays the invoice" |
2797 | msgstr "Dagboekregel waarmee de incasso-opdracht de factuur voldoet" |
2798 | |
2799 | |
2800 | === added directory 'account_direct_debit/migrations' |
2801 | === added directory 'account_direct_debit/migrations/7.0.2' |
2802 | === added file 'account_direct_debit/migrations/7.0.2/pre-migration.py' |
2803 | --- account_direct_debit/migrations/7.0.2/pre-migration.py 1970-01-01 00:00:00 +0000 |
2804 | +++ account_direct_debit/migrations/7.0.2/pre-migration.py 2013-06-26 21:16:23 +0000 |
2805 | @@ -0,0 +1,57 @@ |
2806 | +# -*- coding: utf-8 -*- |
2807 | +############################################################################## |
2808 | +# |
2809 | +# Copyright (C) 2013 Therp BV (<http://therp.nl>). |
2810 | +# |
2811 | +# All other contributions are (C) by their respective contributors |
2812 | +# |
2813 | +# All Rights Reserved |
2814 | +# |
2815 | +# This program is free software: you can redistribute it and/or modify |
2816 | +# it under the terms of the GNU Affero General Public License as |
2817 | +# published by the Free Software Foundation, either version 3 of the |
2818 | +# License, or (at your option) any later version. |
2819 | +# |
2820 | +# This program is distributed in the hope that it will be useful, |
2821 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2822 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2823 | +# GNU Affero General Public License for more details. |
2824 | +# |
2825 | +# You should have received a copy of the GNU Affero General Public License |
2826 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2827 | +# |
2828 | +############################################################################## |
2829 | + |
2830 | +def rename_columns(cr, column_spec): |
2831 | + """ |
2832 | + Rename table columns. Taken from OpenUpgrade. |
2833 | + |
2834 | + :param column_spec: a hash with table keys, with lists of tuples as values. \ |
2835 | + Tuples consist of (old_name, new_name). |
2836 | + |
2837 | + """ |
2838 | + for table in column_spec.keys(): |
2839 | + for (old, new) in column_spec[table]: |
2840 | + logger.info("table %s, column %s: renaming to %s", |
2841 | + table, old, new) |
2842 | + cr.execute('ALTER TABLE "%s" RENAME "%s" TO "%s"' % (table, old, new,)) |
2843 | + cr.execute('DROP INDEX IF EXISTS "%s_%s_index"' % (table, old)) |
2844 | + |
2845 | +def migrate(cr, version): |
2846 | + if not version: |
2847 | + return |
2848 | + |
2849 | + # workflow state moved to another module |
2850 | + cr.execute( |
2851 | + """ |
2852 | + UPDATE ir_model_data |
2853 | + SET module = 'account_banking_payment' |
2854 | + WHERE name = 'trans_done_sent' |
2855 | + AND module = 'account_direct_debit' |
2856 | + """) |
2857 | + |
2858 | + # rename field debit_move_line_id |
2859 | + rename_columns(cr, { |
2860 | + 'payment_line': [ |
2861 | + ('debit_move_line_id', 'transit_move_line_id'), |
2862 | + ]}) |
2863 | |
2864 | === modified file 'account_direct_debit/model/__init__.py' |
2865 | --- account_direct_debit/model/__init__.py 2011-12-11 15:00:41 +0000 |
2866 | +++ account_direct_debit/model/__init__.py 2013-06-26 21:16:23 +0000 |
2867 | @@ -1,3 +1,5 @@ |
2868 | import account_payment |
2869 | +import payment_line |
2870 | import account_move_line |
2871 | import account_invoice |
2872 | +import payment_order_create |
2873 | |
2874 | === modified file 'account_direct_debit/model/account_invoice.py' |
2875 | --- account_direct_debit/model/account_invoice.py 2012-01-12 10:58:49 +0000 |
2876 | +++ account_direct_debit/model/account_invoice.py 2013-06-26 21:16:23 +0000 |
2877 | @@ -1,6 +1,29 @@ |
2878 | # -*- coding: utf-8 -*- |
2879 | -from osv import osv, fields |
2880 | -from tools.translate import _ |
2881 | +############################################################################## |
2882 | +# |
2883 | +# Copyright (C) 2011 - 2013 Therp BV (<http://therp.nl>). |
2884 | +# |
2885 | +# All other contributions are (C) by their respective contributors |
2886 | +# |
2887 | +# All Rights Reserved |
2888 | +# |
2889 | +# This program is free software: you can redistribute it and/or modify |
2890 | +# it under the terms of the GNU Affero General Public License as |
2891 | +# published by the Free Software Foundation, either version 3 of the |
2892 | +# License, or (at your option) any later version. |
2893 | +# |
2894 | +# This program is distributed in the hope that it will be useful, |
2895 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2896 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2897 | +# GNU Affero General Public License for more details. |
2898 | +# |
2899 | +# You should have received a copy of the GNU Affero General Public License |
2900 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
2901 | +# |
2902 | +############################################################################## |
2903 | + |
2904 | +from openerp.osv import orm, fields |
2905 | +from openerp.tools.translate import _ |
2906 | |
2907 | """ |
2908 | This module adds support for Direct debit orders as applicable |
2909 | @@ -98,7 +121,7 @@ |
2910 | open invoices with a matured invoice- or due date. |
2911 | """ |
2912 | |
2913 | -class account_invoice(osv.osv): |
2914 | +class account_invoice(orm.Model): |
2915 | _inherit = "account.invoice" |
2916 | |
2917 | def __init__(self, pool, cr): |
2918 | @@ -139,5 +162,3 @@ |
2919 | if not invoice['reconciled']: |
2920 | return False |
2921 | return True |
2922 | - |
2923 | -account_invoice() |
2924 | |
2925 | === modified file 'account_direct_debit/model/account_move_line.py' |
2926 | --- account_direct_debit/model/account_move_line.py 2013-04-24 14:36:15 +0000 |
2927 | +++ account_direct_debit/model/account_move_line.py 2013-06-26 21:16:23 +0000 |
2928 | @@ -2,9 +2,8 @@ |
2929 | ############################################################################## |
2930 | # |
2931 | # OpenERP, Open Source Management Solution |
2932 | -# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>). |
2933 | -# This module additional (C) 2011 Therp BV (<http://therp.nl>). |
2934 | -# (C) 2011 Smile Benelux (<http://smile.fr>). |
2935 | +# This module (C) 2011 - 2013 Therp BV (<http://therp.nl>). |
2936 | +# (C) 2011 Smile Benelux (<http://smile.fr>). |
2937 | # |
2938 | # This program is free software: you can redistribute it and/or modify |
2939 | # it under the terms of the GNU Affero General Public License as |
2940 | @@ -22,10 +21,9 @@ |
2941 | ############################################################################## |
2942 | |
2943 | from operator import itemgetter |
2944 | -from osv import fields, osv |
2945 | -from tools.translate import _ |
2946 | +from openerp.osv import fields, orm |
2947 | |
2948 | -class account_move_line(osv.osv): |
2949 | +class account_move_line(orm.Model): |
2950 | _inherit = "account.move.line" |
2951 | |
2952 | def amount_to_receive(self, cr, uid, ids, name, arg={}, context=None): |
2953 | @@ -55,6 +53,9 @@ |
2954 | return r |
2955 | |
2956 | def _to_receive_search(self, cr, uid, obj, name, args, context=None): |
2957 | + """ |
2958 | + Reverse of account_payment/account_move_line.py:_to_pay_search() |
2959 | + """ |
2960 | if not args: |
2961 | return [] |
2962 | line_obj = self.pool.get('account.move.line') |
2963 | @@ -86,70 +87,9 @@ |
2964 | return [('id', '=', '0')] |
2965 | return [('id', 'in', map(lambda x:x[0], res))] |
2966 | |
2967 | - def _dummy(self, cr, user, ids, name, arg, context=None): |
2968 | - res = {} |
2969 | - if ids: |
2970 | - res = dict([(x, False) for x in ids]) |
2971 | - return res |
2972 | - |
2973 | - def _invoice_payment_term_id_search( |
2974 | - self, cr, uid, obj, name, args, context=None): |
2975 | - """ |
2976 | - Allow to search move lines associated with an invoice with |
2977 | - a particular payment term |
2978 | - """ |
2979 | - if not args: |
2980 | - return [] |
2981 | - invoice_obj = self.pool.get('account.invoice') |
2982 | - invoice_ids = invoice_obj.search( |
2983 | - cr, uid, [('payment_term', args[0][1], args[0][2])], |
2984 | - context=context) |
2985 | - operator = 'in' # (args[0][1] not in ['in', '=', '==', 'like', 'ilike'] |
2986 | - # and 'not in' or 'in') |
2987 | - if not invoice_ids: |
2988 | - return [('id', operator, [])] |
2989 | - cr.execute('SELECT l.id ' \ |
2990 | - 'FROM account_move_line l, account_invoice i ' \ |
2991 | - 'WHERE l.move_id = i.move_id AND i.id in %s', (tuple(invoice_ids),)) |
2992 | - res = cr.fetchall() |
2993 | - if not res: |
2994 | - return [('id', '=', False)] |
2995 | - return [('id', operator, [x[0] for x in res])] |
2996 | - |
2997 | - def _invoice_state_search(self, cr, uid, obj, name, args, context=None): |
2998 | - if not args: |
2999 | - return [] |
3000 | - invoice_obj = self.pool.get('account.invoice') |
3001 | - invoice_ids = invoice_obj.search( |
3002 | - cr, uid, [('state', args[0][1], args[0][2])], |
3003 | - context=context) |
3004 | - operator = 'in' # (args[0][1] not in ['in', '=', '==', 'like', 'ilike'] |
3005 | - # and 'not in' or 'in') |
3006 | - if not invoice_ids: |
3007 | - return [('id', operator, [])] |
3008 | - cr.execute('SELECT l.id ' \ |
3009 | - 'FROM account_move_line l, account_invoice i ' \ |
3010 | - 'WHERE l.move_id = i.move_id AND i.id in %s', (tuple(invoice_ids),)) |
3011 | - res = cr.fetchall() |
3012 | - if not res: |
3013 | - return [('id', '=', False)] |
3014 | - return [('id', operator, [x[0] for x in res])] |
3015 | - |
3016 | _columns = { |
3017 | 'amount_to_receive': fields.function( |
3018 | amount_to_receive, method=True, |
3019 | type='float', string='Amount to receive', |
3020 | fnct_search=_to_receive_search), |
3021 | - 'payment_term_id': fields.function( |
3022 | - _dummy, method=True, |
3023 | - string='Select by invoice payment term', |
3024 | - type='many2one', relation='account.payment.term', |
3025 | - fnct_search=_invoice_payment_term_id_search), |
3026 | - 'invoice_state': fields.function( |
3027 | - _dummy, method=True, |
3028 | - string='Select by invoice state', |
3029 | - type='char', size=24, |
3030 | - fnct_search=_invoice_state_search), |
3031 | } |
3032 | - |
3033 | -account_move_line() |
3034 | |
3035 | === modified file 'account_direct_debit/model/account_payment.py' |
3036 | --- account_direct_debit/model/account_payment.py 2013-01-21 11:30:46 +0000 |
3037 | +++ account_direct_debit/model/account_payment.py 2013-06-26 21:16:23 +0000 |
3038 | @@ -1,36 +1,9 @@ |
3039 | # -*- coding: utf-8 -*- |
3040 | -import time |
3041 | -from osv import osv, fields |
3042 | +from openerp.osv import orm, fields |
3043 | import netsvc |
3044 | from tools.translate import _ |
3045 | |
3046 | -class payment_mode(osv.osv): |
3047 | - _inherit = 'payment.mode' |
3048 | - _columns = { |
3049 | - 'transfer_account_id': fields.many2one( |
3050 | - 'account.account', 'Transfer account', |
3051 | - domain=[('type', '=', 'other'), |
3052 | - ('reconcile', '=', True)], |
3053 | - help=('Pay off lines in sent orders with a ' + |
3054 | - 'move on this account. For debit type modes only. ' + |
3055 | - 'You can only select accounts of type regular that ' + |
3056 | - 'are marked for reconciliation'), |
3057 | - ), |
3058 | - 'transfer_journal_id': fields.many2one( |
3059 | - 'account.journal', 'Transfer journal', |
3060 | - help=('Journal to write payment entries when confirming ' + |
3061 | - 'a debit order of this mode'), |
3062 | - ), |
3063 | - 'payment_term_ids': fields.many2many( |
3064 | - 'account.payment.term', 'account_payment_order_terms_rel', |
3065 | - 'mode_id', 'term_id', 'Payment terms', |
3066 | - help=('Limit selected invoices to invoices with these payment ' + |
3067 | - 'terms') |
3068 | - ), |
3069 | - } |
3070 | -payment_mode() |
3071 | - |
3072 | -class payment_order(osv.osv): |
3073 | +class payment_order(orm.Model): |
3074 | _inherit = 'payment.order' |
3075 | |
3076 | def fields_view_get(self, cr, user, view_id=None, view_type='form', |
3077 | @@ -56,56 +29,11 @@ |
3078 | context['search_payment_order_type'])] |
3079 | # the magic is in the value of the selection |
3080 | res['fields']['mode']['selection'] = mode_obj._name_search( |
3081 | - cr, user, args=domain) |
3082 | + cr, user, args=domain, context=context) |
3083 | # also update the domain |
3084 | res['fields']['mode']['domain'] = domain |
3085 | return res |
3086 | |
3087 | - def debit_reconcile_transfer(self, cr, uid, payment_order_id, |
3088 | - amount, currency, context=None): |
3089 | - """ |
3090 | - During import of bank statements, create the reconcile on the transfer |
3091 | - account containing all the open move lines on the transfer account. |
3092 | - """ |
3093 | - move_line_obj = self.pool.get('account.move.line') |
3094 | - order = self.browse(cr, uid, payment_order_id, context) |
3095 | - line_ids = [] |
3096 | - reconcile_id = False |
3097 | - for order_line in order.line_ids: |
3098 | - for line in order_line.debit_move_line_id.move_id.line_id: |
3099 | - if line.account_id.type == 'other' and not line.reconcile_id: |
3100 | - line_ids.append(line.id) |
3101 | - if self.pool.get('res.currency').is_zero( |
3102 | - cr, uid, currency, |
3103 | - move_line_obj.get_balance(cr, uid, line_ids) - amount): |
3104 | - reconcile_id = self.pool.get('account.move.reconcile').create( |
3105 | - cr, uid, |
3106 | - {'type': 'auto', 'line_id': [(6, 0, line_ids)]}, |
3107 | - context) |
3108 | - # set direct debit order to finished state |
3109 | - wf_service = netsvc.LocalService('workflow') |
3110 | - wf_service.trg_validate( |
3111 | - uid, 'payment.order', payment_order_id, 'done', cr) |
3112 | - return reconcile_id |
3113 | - |
3114 | - def debit_unreconcile_transfer(self, cr, uid, payment_order_id, reconcile_id, |
3115 | - amount, currency, context=None): |
3116 | - """ |
3117 | - Due to a cancelled bank statements import, unreconcile the move on |
3118 | - the transfer account. Delegate the conditions to the workflow. |
3119 | - Raise on failure for rollback. |
3120 | - """ |
3121 | - self.pool.get('account.move.reconcile').unlink( |
3122 | - cr, uid, reconcile_id, context=context) |
3123 | - wkf_ok = netsvc.LocalService('workflow').trg_validate( |
3124 | - uid, 'payment.order', payment_order_id, 'undo_done', cr) |
3125 | - if not wkf_ok: |
3126 | - raise osv.except_osv( |
3127 | - _("Cannot unreconcile"), |
3128 | - _("Cannot unreconcile debit order: "+ |
3129 | - "Workflow will not allow it.")) |
3130 | - return True |
3131 | - |
3132 | def test_undo_done(self, cr, uid, ids, context=None): |
3133 | """ |
3134 | Called from the workflow. Used to unset done state on |
3135 | @@ -117,362 +45,5 @@ |
3136 | for line in order.line_ids: |
3137 | if line.storno: |
3138 | return False |
3139 | - else: |
3140 | - # TODO: define conditions for 'payment' orders |
3141 | - return False |
3142 | - return True |
3143 | - |
3144 | - def action_sent(self, cr, uid, ids, context=None): |
3145 | - """ |
3146 | - Create the moves that pay off the move lines from |
3147 | - the debit order. This happens when the debit order file is |
3148 | - generated. |
3149 | - """ |
3150 | - res = super(payment_order, self).action_sent( |
3151 | - cr, uid, ids, context) |
3152 | - |
3153 | - account_move_obj = self.pool.get('account.move') |
3154 | - account_move_line_obj = self.pool.get('account.move.line') |
3155 | - payment_line_obj = self.pool.get('payment.line') |
3156 | - for order in self.browse(cr, uid, ids, context=context): |
3157 | - if order.payment_order_type != 'debit': |
3158 | - continue |
3159 | - for line in order.line_ids: |
3160 | - # basic checks |
3161 | - if not line.move_line_id: |
3162 | - raise osv.except_osv( |
3163 | - _('Error'), |
3164 | - _('No move line provided for line %s') % line.name) |
3165 | - if line.move_line_id.reconcile_id: |
3166 | - raise osv.except_osv( |
3167 | - _('Error'), |
3168 | - _('Move line %s has already been paid/reconciled') % |
3169 | - line.move_line_id.name |
3170 | - ) |
3171 | - |
3172 | - move_id = account_move_obj.create(cr, uid, { |
3173 | - 'journal_id': order.mode.transfer_journal_id.id, |
3174 | - 'name': 'Debit order %s' % line.move_line_id.move_id.name, |
3175 | - 'reference': 'DEB%s' % line.move_line_id.move_id.name, |
3176 | - }, context=context) |
3177 | - |
3178 | - # TODO: take multicurrency into account |
3179 | - |
3180 | - # create the debit move line on the transfer account |
3181 | - vals = { |
3182 | - 'name': 'Debit order for %s' % ( |
3183 | - line.move_line_id.invoice and |
3184 | - line.move_line_id.invoice.number or |
3185 | - line.move_line_id.name), |
3186 | - 'move_id': move_id, |
3187 | - 'partner_id': line.partner_id.id, |
3188 | - 'account_id': order.mode.transfer_account_id.id, |
3189 | - 'credit': 0.0, |
3190 | - 'debit': line.amount, |
3191 | - 'date': time.strftime('%Y-%m-%d'), |
3192 | - } |
3193 | - transfer_move_line_id = account_move_line_obj.create( |
3194 | - cr, uid, vals, context=context) |
3195 | - |
3196 | - # create the debit move line on the receivable account |
3197 | - vals.update({ |
3198 | - 'account_id': line.move_line_id.account_id.id, |
3199 | - 'credit': line.amount, |
3200 | - 'debit': 0.0, |
3201 | - }) |
3202 | - reconcile_move_line_id = account_move_line_obj.create( |
3203 | - cr, uid, vals, context=context) |
3204 | - |
3205 | - # register the debit move line on the payment line |
3206 | - # and call reconciliation on it |
3207 | - payment_line_obj.write( |
3208 | - cr, uid, line.id, |
3209 | - {'debit_move_line_id': reconcile_move_line_id}, |
3210 | - context=context) |
3211 | - |
3212 | - payment_line_obj.debit_reconcile( |
3213 | - cr, uid, line.id, context=context) |
3214 | - account_move_obj.post(cr, uid, [move_id], context=context) |
3215 | - return res |
3216 | - |
3217 | -payment_order() |
3218 | - |
3219 | -class payment_line(osv.osv): |
3220 | - _inherit = 'payment.line' |
3221 | - |
3222 | - def debit_storno(self, cr, uid, payment_line_id, amount, |
3223 | - currency, storno_retry=True, context=None): |
3224 | - """ |
3225 | - The processing of a storno is triggered by a debit |
3226 | - transfer on one of the company's bank accounts. |
3227 | - This method offers to re-reconcile the original debit |
3228 | - payment. For this purpose, we have registered that |
3229 | - payment move on the payment line. |
3230 | - |
3231 | - Return the (now incomplete) reconcile id. The caller MUST |
3232 | - re-reconcile this reconcile with the bank transfer and |
3233 | - re-open the associated invoice. |
3234 | - |
3235 | - :param payment_line_id: the single payment line id |
3236 | - :param amount: the (signed) amount debited from the bank account |
3237 | - :param currency: the bank account's currency *browse object* |
3238 | - :param boolean storno_retry: when True, attempt to reopen the invoice, \ |
3239 | - set the invoice to 'Debit denied' otherwise. |
3240 | - :return: an incomplete reconcile for the caller to fill |
3241 | - :rtype: database id of an account.move.reconcile resource. |
3242 | - """ |
3243 | - |
3244 | - move_line_obj = self.pool.get('account.move.line') |
3245 | - reconcile_obj = self.pool.get('account.move.reconcile') |
3246 | - line = self.browse(cr, uid, payment_line_id) |
3247 | - reconcile_id = False |
3248 | - if (line.debit_move_line_id and not line.storno and |
3249 | - self.pool.get('res.currency').is_zero( |
3250 | - cr, uid, currency, ( |
3251 | - (line.debit_move_line_id.credit or 0.0) - |
3252 | - (line.debit_move_line_id.debit or 0.0) + amount))): |
3253 | - # Two different cases, full and partial |
3254 | - # Both cases differ subtly in the procedure to follow |
3255 | - # Needs refractoring, but why is this not in the OpenERP API? |
3256 | - # Actually, given the nature of a direct debit order and storno, |
3257 | - # we should not need to take partial into account on the side of |
3258 | - # the debit_move_line. |
3259 | - if line.debit_move_line_id.reconcile_partial_id: |
3260 | - reconcile_id = line.debit_move_line_id.reconcile_partial_id.id |
3261 | - attribute = 'reconcile_partial_id' |
3262 | - if len(line.debit_move_line_id.reconcile_id.line_partial_ids) == 2: |
3263 | - # reuse the simple reconcile for the storno transfer |
3264 | - reconcile_obj.write( |
3265 | - cr, uid, reconcile_id, { |
3266 | - 'line_id': [(6, 0, line.debit_move_line_id.id)], |
3267 | - 'line_partial_ids': [(6, 0, [])], |
3268 | - }, context=context) |
3269 | - else: |
3270 | - # split up the original reconcile in a partial one |
3271 | - # and a new one for reconciling the storno transfer |
3272 | - reconcile_obj.write( |
3273 | - cr, uid, reconcile_id, { |
3274 | - 'line_partial_ids': [(3, line.debit_move_line_id.id)], |
3275 | - }, context=context) |
3276 | - reconcile_id = reconcile_obj.create( |
3277 | - cr, uid, { |
3278 | - 'type': 'auto', |
3279 | - 'line_id': [(6, 0, line.debit_move_line_id.id)], |
3280 | - }, context=context) |
3281 | - elif line.debit_move_line_id.reconcile_id: |
3282 | - reconcile_id = line.debit_move_line_id.reconcile_id.id |
3283 | - if len(line.debit_move_line_id.reconcile_id.line_id) == 2: |
3284 | - # reuse the simple reconcile for the storno transfer |
3285 | - reconcile_obj.write( |
3286 | - cr, uid, reconcile_id, { |
3287 | - 'line_id': [(6, 0, [line.debit_move_line_id.id])] |
3288 | - }, context=context) |
3289 | - else: |
3290 | - # split up the original reconcile in a partial one |
3291 | - # and a new one for reconciling the storno transfer |
3292 | - partial_ids = [ |
3293 | - x.id for x in line.debit_move_line_id.reconcile_id.line_id |
3294 | - if x.id != line.debit_move_line_id.id |
3295 | - ] |
3296 | - reconcile_obj.write( |
3297 | - cr, uid, reconcile_id, { |
3298 | - 'line_partial_ids': [(6, 0, partial_ids)], |
3299 | - 'line_id': [(6, 0, [])], |
3300 | - }, context=context) |
3301 | - reconcile_id = reconcile_obj.create( |
3302 | - cr, uid, { |
3303 | - 'type': 'auto', |
3304 | - 'line_id': [(6, 0, line.debit_move_line_id.id)], |
3305 | - }, context=context) |
3306 | - # mark the payment line for storno processed |
3307 | - if reconcile_id: |
3308 | - self.write(cr, uid, [payment_line_id], |
3309 | - {'storno': True}, context=context) |
3310 | - # put forth the invoice workflow |
3311 | - if line.move_line_id.invoice: |
3312 | - activity = (storno_retry and 'open_test' |
3313 | - or 'invoice_debit_denied') |
3314 | - netsvc.LocalService("workflow").trg_validate( |
3315 | - uid, 'account.invoice', line.move_line_id.invoice.id, |
3316 | - activity, cr) |
3317 | - return reconcile_id |
3318 | - |
3319 | - def get_storno_account_id(self, cr, uid, payment_line_id, amount, |
3320 | - currency, context=None): |
3321 | - """ |
3322 | - Check the match of the arguments, and return the account associated |
3323 | - with the storno. |
3324 | - Used in account_banking interactive mode |
3325 | - |
3326 | - :param payment_line_id: the single payment line id |
3327 | - :param amount: the (signed) amount debited from the bank account |
3328 | - :param currency: the bank account's currency *browse object* |
3329 | - :return: an account if there is a full match, False otherwise |
3330 | - :rtype: database id of an account.account resource. |
3331 | - """ |
3332 | - |
3333 | - line = self.browse(cr, uid, payment_line_id) |
3334 | - account_id = False |
3335 | - if (line.debit_move_line_id and not line.storno and |
3336 | - self.pool.get('res.currency').is_zero( |
3337 | - cr, uid, currency, ( |
3338 | - (line.debit_move_line_id.credit or 0.0) - |
3339 | - (line.debit_move_line_id.debit or 0.0) + amount))): |
3340 | - account_id = line.debit_move_line_id.account_id.id |
3341 | - return account_id |
3342 | - |
3343 | - def debit_reconcile(self, cr, uid, payment_line_id, context=None): |
3344 | - """ |
3345 | - Reconcile a debit order's payment line with the the move line |
3346 | - that it is based on. Called from payment_order.action_sent(). |
3347 | - As the amount is derived directly from the counterpart move line, |
3348 | - we do not expect a write off. Take partially reconcilions into |
3349 | - account though. |
3350 | - |
3351 | - :param payment_line_id: the single id of the canceled payment line |
3352 | - """ |
3353 | - |
3354 | - if isinstance(payment_line_id, (list, tuple)): |
3355 | - payment_line_id = payment_line_id[0] |
3356 | - reconcile_obj = self.pool.get('account.move.reconcile') |
3357 | - move_line_obj = self.pool.get('account.move.line') |
3358 | - payment_line = self.browse(cr, uid, payment_line_id, context=context) |
3359 | - |
3360 | - debit_move_line = payment_line.debit_move_line_id |
3361 | - torec_move_line = payment_line.move_line_id |
3362 | - |
3363 | - if payment_line.storno: |
3364 | - raise osv.except_osv( |
3365 | - _('Can not reconcile'), |
3366 | - _('Cancelation of payment line \'%s\' has already been ' + |
3367 | - 'processed') % payment_line.name) |
3368 | - if (not debit_move_line or not torec_move_line): |
3369 | - raise osv.except_osv( |
3370 | - _('Can not reconcile'), |
3371 | - _('No move line for line %s') % payment_line.name) |
3372 | - if torec_move_line.reconcile_id: # torec_move_line.reconcile_partial_id: |
3373 | - raise osv.except_osv( |
3374 | - _('Error'), |
3375 | - _('Move line %s has already been reconciled') % |
3376 | - torec_move_line.name |
3377 | - ) |
3378 | - if debit_move_line.reconcile_id or debit_move_line.reconcile_partial_id: |
3379 | - raise osv.except_osv( |
3380 | - _('Error'), |
3381 | - _('Move line %s has already been reconciled') % |
3382 | - debit_move_line.name |
3383 | - ) |
3384 | - |
3385 | - def is_zero(total): |
3386 | - return self.pool.get('res.currency').is_zero( |
3387 | - cr, uid, debit_move_line.company_id.currency_id, total) |
3388 | - |
3389 | - line_ids = [debit_move_line.id, torec_move_line.id] |
3390 | - if torec_move_line.reconcile_partial_id: |
3391 | - line_ids = [ |
3392 | - x.id for x in debit_move_line.reconcile_partial_id.line_partial_ids] + [torec_move_line_id] |
3393 | - |
3394 | - total = move_line_obj.get_balance(cr, uid, line_ids) |
3395 | - vals = { |
3396 | - 'type': 'auto', |
3397 | - 'line_id': is_zero(total) and [(6, 0, line_ids)] or [(6, 0, [])], |
3398 | - 'line_partial_ids': is_zero(total) and [(6, 0, [])] or [(6, 0, line_ids)], |
3399 | - } |
3400 | - |
3401 | - if torec_move_line.reconcile_partial_id: |
3402 | - reconcile_obj.write( |
3403 | - cr, uid, debit_move_line.reconcile_partial_id.id, |
3404 | - vals, context=context) |
3405 | - else: |
3406 | - reconcile_obj.create( |
3407 | - cr, uid, vals, context=context) |
3408 | - for line_id in line_ids: |
3409 | - netsvc.LocalService("workflow").trg_trigger( |
3410 | - uid, 'account.move.line', line_id, cr) |
3411 | - |
3412 | - # If a bank transaction of a storno was first confirmed |
3413 | - # and now canceled (the invoice is now in state 'debit_denied' |
3414 | - if torec_move_line.invoice: |
3415 | - netsvc.LocalService("workflow").trg_validate( |
3416 | - uid, 'account.invoice', torec_move_line.invoice.id, |
3417 | - 'undo_debit_denied', cr) |
3418 | - |
3419 | - |
3420 | - |
3421 | - _columns = { |
3422 | - 'debit_move_line_id': fields.many2one( |
3423 | - # this line is part of the credit side of move 2a |
3424 | - # from the documentation |
3425 | - 'account.move.line', 'Debit move line', |
3426 | - readonly=True, |
3427 | - help="Move line through which the debit order pays the invoice"), |
3428 | - 'storno': fields.boolean( |
3429 | - 'Storno', |
3430 | - readonly=True, |
3431 | - help=("If this is true, the debit order has been canceled " + |
3432 | - "by the bank or by the customer")), |
3433 | - } |
3434 | -payment_line() |
3435 | - |
3436 | - |
3437 | -class payment_order_create(osv.osv_memory): |
3438 | - _inherit = 'payment.order.create' |
3439 | - |
3440 | - def search_entries(self, cr, uid, ids, context=None): |
3441 | - """ |
3442 | - This method taken from account_payment module. |
3443 | - We adapt the domain based on the payment_order_type |
3444 | - """ |
3445 | - line_obj = self.pool.get('account.move.line') |
3446 | - mod_obj = self.pool.get('ir.model.data') |
3447 | - if context is None: |
3448 | - context = {} |
3449 | - data = self.read(cr, uid, ids, [], context=context)[0] |
3450 | - search_due_date = data['duedate'] |
3451 | - |
3452 | - ### start account_direct_debit ### |
3453 | - payment = self.pool.get('payment.order').browse( |
3454 | - cr, uid, context['active_id'], context=context) |
3455 | - # Search for move line to pay: |
3456 | - if payment.payment_order_type == 'debit': |
3457 | - domain = [ |
3458 | - ('reconcile_id', '=', False), |
3459 | - ('account_id.type', '=', 'receivable'), |
3460 | - ('invoice_state', '!=', 'debit_denied'), |
3461 | - ('amount_to_receive', '>', 0), |
3462 | - ] |
3463 | - else: |
3464 | - domain = [ |
3465 | - ('reconcile_id', '=', False), |
3466 | - ('account_id.type', '=', 'payable'), |
3467 | - ('amount_to_pay', '>', 0) |
3468 | - ] |
3469 | - domain.append(('company_id', '=', payment.mode.company_id.id)) |
3470 | - # apply payment term filter |
3471 | - if payment.mode.payment_term_ids: |
3472 | - domain = domain + [ |
3473 | - ('payment_term_id', 'in', |
3474 | - [term.id for term in payment.mode.payment_term_ids] |
3475 | - ) |
3476 | - ] |
3477 | - # domain = [('reconcile_id', '=', False), ('account_id.type', '=', 'payable'), ('amount_to_pay', '>', 0)] |
3478 | - ### end account_direct_debit ### |
3479 | - |
3480 | - domain = domain + ['|', ('date_maturity', '<=', search_due_date), ('date_maturity', '=', False)] |
3481 | - line_ids = line_obj.search(cr, uid, domain, context=context) |
3482 | - context.update({'line_ids': line_ids}) |
3483 | - model_data_ids = mod_obj.search(cr, uid,[('model', '=', 'ir.ui.view'), ('name', '=', 'view_create_payment_order_lines')], context=context) |
3484 | - resource_id = mod_obj.read(cr, uid, model_data_ids, fields=['res_id'], context=context)[0]['res_id'] |
3485 | - return {'name': ('Entry Lines'), |
3486 | - 'context': context, |
3487 | - 'view_type': 'form', |
3488 | - 'view_mode': 'form', |
3489 | - 'res_model': 'payment.order.create', |
3490 | - 'views': [(resource_id,'form')], |
3491 | - 'type': 'ir.actions.act_window', |
3492 | - 'target': 'new', |
3493 | - } |
3494 | -payment_order_create() |
3495 | - |
3496 | - |
3497 | - |
3498 | + return super(payment_order, self).test_undo_done( |
3499 | + cr, uid, ids, context=context) |
3500 | |
3501 | === added file 'account_direct_debit/model/payment_line.py' |
3502 | --- account_direct_debit/model/payment_line.py 1970-01-01 00:00:00 +0000 |
3503 | +++ account_direct_debit/model/payment_line.py 2013-06-26 21:16:23 +0000 |
3504 | @@ -0,0 +1,152 @@ |
3505 | +# -*- coding: utf-8 -*- |
3506 | +from openerp.osv import orm, fields |
3507 | +import netsvc |
3508 | +from tools.translate import _ |
3509 | + |
3510 | +class payment_line(orm.Model): |
3511 | + _inherit = 'payment.line' |
3512 | + |
3513 | + def debit_storno(self, cr, uid, payment_line_id, amount, |
3514 | + currency, storno_retry=True, context=None): |
3515 | + """ |
3516 | + The processing of a storno is triggered by a debit |
3517 | + transfer on one of the company's bank accounts. |
3518 | + This method offers to re-reconcile the original debit |
3519 | + payment. For this purpose, we have registered that |
3520 | + payment move on the payment line. |
3521 | + |
3522 | + Return the (now incomplete) reconcile id. The caller MUST |
3523 | + re-reconcile this reconcile with the bank transfer and |
3524 | + re-open the associated invoice. |
3525 | + |
3526 | + :param payment_line_id: the single payment line id |
3527 | + :param amount: the (signed) amount debited from the bank account |
3528 | + :param currency: the bank account's currency *browse object* |
3529 | + :param boolean storno_retry: when True, attempt to reopen the invoice, \ |
3530 | + set the invoice to 'Debit denied' otherwise. |
3531 | + :return: an incomplete reconcile for the caller to fill |
3532 | + :rtype: database id of an account.move.reconcile resource. |
3533 | + """ |
3534 | + |
3535 | + move_line_obj = self.pool.get('account.move.line') |
3536 | + reconcile_obj = self.pool.get('account.move.reconcile') |
3537 | + line = self.browse(cr, uid, payment_line_id) |
3538 | + reconcile_id = False |
3539 | + if (line.transit_move_line_id and not line.storno and |
3540 | + self.pool.get('res.currency').is_zero( |
3541 | + cr, uid, currency, ( |
3542 | + (line.transit_move_line_id.credit or 0.0) - |
3543 | + (line.transit_move_line_id.debit or 0.0) + amount))): |
3544 | + # Two different cases, full and partial |
3545 | + # Both cases differ subtly in the procedure to follow |
3546 | + # Needs refractoring, but why is this not in the OpenERP API? |
3547 | + # Actually, given the nature of a direct debit order and storno, |
3548 | + # we should not need to take partial into account on the side of |
3549 | + # the transit_move_line. |
3550 | + if line.transit_move_line_id.reconcile_partial_id: |
3551 | + reconcile_id = line.transit_move_line_id.reconcile_partial_id.id |
3552 | + attribute = 'reconcile_partial_id' |
3553 | + if len(line.transit_move_line_id.reconcile_id.line_partial_ids) == 2: |
3554 | + # reuse the simple reconcile for the storno transfer |
3555 | + reconcile_obj.write( |
3556 | + cr, uid, reconcile_id, { |
3557 | + 'line_id': [(6, 0, line.transit_move_line_id.id)], |
3558 | + 'line_partial_ids': [(6, 0, [])], |
3559 | + }, context=context) |
3560 | + else: |
3561 | + # split up the original reconcile in a partial one |
3562 | + # and a new one for reconciling the storno transfer |
3563 | + reconcile_obj.write( |
3564 | + cr, uid, reconcile_id, { |
3565 | + 'line_partial_ids': [(3, line.transit_move_line_id.id)], |
3566 | + }, context=context) |
3567 | + reconcile_id = reconcile_obj.create( |
3568 | + cr, uid, { |
3569 | + 'type': 'auto', |
3570 | + 'line_id': [(6, 0, line.transit_move_line_id.id)], |
3571 | + }, context=context) |
3572 | + elif line.transit_move_line_id.reconcile_id: |
3573 | + reconcile_id = line.transit_move_line_id.reconcile_id.id |
3574 | + if len(line.transit_move_line_id.reconcile_id.line_id) == 2: |
3575 | + # reuse the simple reconcile for the storno transfer |
3576 | + reconcile_obj.write( |
3577 | + cr, uid, reconcile_id, { |
3578 | + 'line_id': [(6, 0, [line.transit_move_line_id.id])] |
3579 | + }, context=context) |
3580 | + else: |
3581 | + # split up the original reconcile in a partial one |
3582 | + # and a new one for reconciling the storno transfer |
3583 | + partial_ids = [ |
3584 | + x.id for x in line.transit_move_line_id.reconcile_id.line_id |
3585 | + if x.id != line.transit_move_line_id.id |
3586 | + ] |
3587 | + reconcile_obj.write( |
3588 | + cr, uid, reconcile_id, { |
3589 | + 'line_partial_ids': [(6, 0, partial_ids)], |
3590 | + 'line_id': [(6, 0, [])], |
3591 | + }, context=context) |
3592 | + reconcile_id = reconcile_obj.create( |
3593 | + cr, uid, { |
3594 | + 'type': 'auto', |
3595 | + 'line_id': [(6, 0, line.transit_move_line_id.id)], |
3596 | + }, context=context) |
3597 | + # mark the payment line for storno processed |
3598 | + if reconcile_id: |
3599 | + self.write(cr, uid, [payment_line_id], |
3600 | + {'storno': True}, context=context) |
3601 | + # put forth the invoice workflow |
3602 | + if line.move_line_id.invoice: |
3603 | + activity = (storno_retry and 'open_test' |
3604 | + or 'invoice_debit_denied') |
3605 | + netsvc.LocalService("workflow").trg_validate( |
3606 | + uid, 'account.invoice', line.move_line_id.invoice.id, |
3607 | + activity, cr) |
3608 | + return reconcile_id |
3609 | + |
3610 | + def get_storno_account_id(self, cr, uid, payment_line_id, amount, |
3611 | + currency, context=None): |
3612 | + """ |
3613 | + Check the match of the arguments, and return the account associated |
3614 | + with the storno. |
3615 | + Used in account_banking interactive mode |
3616 | + |
3617 | + :param payment_line_id: the single payment line id |
3618 | + :param amount: the (signed) amount debited from the bank account |
3619 | + :param currency: the bank account's currency *browse object* |
3620 | + :return: an account if there is a full match, False otherwise |
3621 | + :rtype: database id of an account.account resource. |
3622 | + """ |
3623 | + |
3624 | + line = self.browse(cr, uid, payment_line_id) |
3625 | + account_id = False |
3626 | + if (line.transit_move_line_id and not line.storno and |
3627 | + self.pool.get('res.currency').is_zero( |
3628 | + cr, uid, currency, ( |
3629 | + (line.transit_move_line_id.credit or 0.0) - |
3630 | + (line.transit_move_line_id.debit or 0.0) + amount))): |
3631 | + account_id = line.transit_move_line_id.account_id.id |
3632 | + return account_id |
3633 | + |
3634 | + def debit_reconcile(self, cr, uid, payment_line_id, context=None): |
3635 | + """ |
3636 | + Raise if a payment line is passed for which storno is True |
3637 | + """ |
3638 | + if isinstance(payment_line_id, (list, tuple)): |
3639 | + payment_line_id = payment_line_id[0] |
3640 | + payment_line = self.read( |
3641 | + cr, uid, payment_line_id, ['storno', 'name'], context=context) |
3642 | + if payment_line['storno']: |
3643 | + raise orm.except_orm( |
3644 | + _('Can not reconcile'), |
3645 | + _('Cancelation of payment line \'%s\' has already been ' |
3646 | + 'processed') % payment_line['name']) |
3647 | + return super(self, payment_line).debit_reconcile( |
3648 | + cr, uid, payment_line_id, context=context) |
3649 | + |
3650 | + _columns = { |
3651 | + 'storno': fields.boolean( |
3652 | + 'Storno', |
3653 | + readonly=True, |
3654 | + help=("If this is true, the debit order has been canceled " |
3655 | + "by the bank or by the customer")), |
3656 | + } |
3657 | |
3658 | === added file 'account_direct_debit/model/payment_order_create.py' |
3659 | --- account_direct_debit/model/payment_order_create.py 1970-01-01 00:00:00 +0000 |
3660 | +++ account_direct_debit/model/payment_order_create.py 2013-06-26 21:16:23 +0000 |
3661 | @@ -0,0 +1,41 @@ |
3662 | +# -*- coding: utf-8 -*- |
3663 | +############################################################################## |
3664 | +# |
3665 | +# Copyright (C) 2013 Therp BV (<http://therp.nl>). |
3666 | +# |
3667 | +# All other contributions are (C) by their respective contributors |
3668 | +# |
3669 | +# All Rights Reserved |
3670 | +# |
3671 | +# This program is free software: you can redistribute it and/or modify |
3672 | +# it under the terms of the GNU Affero General Public License as |
3673 | +# published by the Free Software Foundation, either version 3 of the |
3674 | +# License, or (at your option) any later version. |
3675 | +# |
3676 | +# This program is distributed in the hope that it will be useful, |
3677 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3678 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3679 | +# GNU Affero General Public License for more details. |
3680 | +# |
3681 | +# You should have received a copy of the GNU Affero General Public License |
3682 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
3683 | +# |
3684 | +############################################################################## |
3685 | + |
3686 | +from openerp.osv import orm |
3687 | + |
3688 | + |
3689 | +class payment_order_create(orm.TransientModel): |
3690 | + _inherit = 'payment.order.create' |
3691 | + |
3692 | + def extend_payment_order_domain( |
3693 | + self, cr, uid, payment_order, domain, context=None): |
3694 | + super(payment_order_create, self).extend_payment_order_domain( |
3695 | + cr, uid, payment_order, domain, context=context) |
3696 | + if payment_order.payment_order_type == 'debit': |
3697 | + domain += [ |
3698 | + ('account_id.type', '=', 'receivable'), |
3699 | + ('invoice.state', '!=', 'debit_denied'), |
3700 | + ('amount_to_receive', '>', 0), |
3701 | + ] |
3702 | + return True |
3703 | |
3704 | === modified file 'account_direct_debit/view/account_invoice.xml' |
3705 | --- account_direct_debit/view/account_invoice.xml 2012-05-01 20:36:44 +0000 |
3706 | +++ account_direct_debit/view/account_invoice.xml 2013-06-26 21:16:23 +0000 |
3707 | @@ -4,7 +4,6 @@ |
3708 | <record id="invoice_form" model="ir.ui.view"> |
3709 | <field name="name">account.invoice.form</field> |
3710 | <field name="model">account.invoice</field> |
3711 | - <field name="type">form</field> |
3712 | <field name="inherit_id" ref="account.invoice_form"/> |
3713 | <field name="arch" type="xml"> |
3714 | <data> |
3715 | @@ -16,14 +15,6 @@ |
3716 | <!-- button name="invoice_open" position="attributes"> |
3717 | <attribute name="states">draft,proforma2,debit_denied</attribute> |
3718 | </button --> |
3719 | - <button string='Re-Open' position="attributes"> |
3720 | - <attribute name="states">paid,debit_denied</attribute> |
3721 | - <!-- |
3722 | - unintentional fix of |
3723 | - https://bugs.launchpad.net/openobject-addons/+bug/807543 |
3724 | - --> |
3725 | - <attribute name="groups"/> |
3726 | - </button> |
3727 | <button name="invoice_open" position="after"> |
3728 | <button name="invoice_debit_denied" states="paid" |
3729 | string="Debit Denied" icon="gtk-cancel"/> |
3730 | @@ -38,7 +29,11 @@ |
3731 | <field name="inherit_id" ref="account.view_account_invoice_filter"/> |
3732 | <field name="arch" type="xml"> |
3733 | <filter name="invoices" position="after"> |
3734 | - <filter name="debit_denied" icon="terp-dolar_ok!" string="Debit denied" domain="[('state','=','debit_denied')]" help="Show only invoices with state Debit denied"/> |
3735 | + <filter name="debit_denied" icon="terp-dolar_ok!" |
3736 | + string="Debit denied" |
3737 | + domain="[('state','=','debit_denied')]" |
3738 | + help="Show only invoices with state Debit denied" |
3739 | + /> |
3740 | </filter> |
3741 | </field> |
3742 | </record> |
3743 | |
3744 | === modified file 'account_direct_debit/view/account_payment.xml' |
3745 | --- account_direct_debit/view/account_payment.xml 2013-01-21 11:19:04 +0000 |
3746 | +++ account_direct_debit/view/account_payment.xml 2013-06-26 21:16:23 +0000 |
3747 | @@ -1,6 +1,7 @@ |
3748 | <?xml version="1.0" encoding="utf-8"?> |
3749 | <openerp> |
3750 | <data> |
3751 | + |
3752 | <!-- distinguish between payment orders and debit orders in the menu --> |
3753 | <record id="account_payment.action_payment_order_tree" model="ir.actions.act_window"> |
3754 | <field name="domain">[('payment_order_type', '=', 'payment')]</field> |
3755 | @@ -24,7 +25,6 @@ |
3756 | <record id="view_payment_order_form" model="ir.ui.view"> |
3757 | <field name="name">payment.order.form</field> |
3758 | <field name="model">payment.order</field> |
3759 | - <field name="type">form</field> |
3760 | <field name="inherit_id" ref="account_payment.view_payment_order_form"/> |
3761 | <field name="priority" eval="60"/> |
3762 | <field name="arch" type="xml"> |
3763 | @@ -46,40 +46,13 @@ |
3764 | icon="gtk-find" |
3765 | /> |
3766 | </xpath> |
3767 | - <!-- the attrs do not work like this, apparently |
3768 | - <xpath expr="//tree[@string='Payment Line']" position="inside"> |
3769 | - <field name="storno" attrs="{'invisible': [(parent.payment_order_type, '!=', 'debit')]}"/> |
3770 | - </xpath> |
3771 | - --> |
3772 | </data> |
3773 | </field> |
3774 | </record> |
3775 | |
3776 | - <!-- Add transfer account for debit type modes --> |
3777 | - <record model="ir.ui.view" id="view_payment_mode_form"> |
3778 | - <field name="name">payment.mode.form add transfer account</field> |
3779 | - <field name="model">payment.mode</field> |
3780 | - <field name="inherit_id" ref="account_banking.view_payment_mode_form_inherit"/> |
3781 | - <field name="type">form</field> |
3782 | - <field name="arch" type="xml"> |
3783 | - <field name="type" position="after"> |
3784 | - <field name="transfer_account_id" |
3785 | - domain="[('type', '=', 'other'), |
3786 | - ('reconcile', '=', True), |
3787 | - ('company_id', '=', company_id)]" |
3788 | - /> |
3789 | - <field name="transfer_journal_id" |
3790 | - domain="[('company_id', '=', company_id)]" |
3791 | - /> |
3792 | - <field name="payment_term_ids"/> |
3793 | - </field> |
3794 | - </field> |
3795 | - </record> |
3796 | - |
3797 | <record id="view_payment_line_tree" model="ir.ui.view"> |
3798 | <field name="name">Payment Lines</field> |
3799 | <field name="model">payment.line</field> |
3800 | - <field name="type">tree</field> |
3801 | <field name="inherit_id" ref="account_payment.view_payment_line_tree"/> |
3802 | <field eval="4" name="priority"/> |
3803 | <field name="arch" type="xml"> |
3804 | @@ -88,5 +61,6 @@ |
3805 | </field> |
3806 | </field> |
3807 | </record> |
3808 | + |
3809 | </data> |
3810 | </openerp> |
3811 | |
3812 | === removed file 'account_direct_debit/workflow/account_payment.xml' |
3813 | --- account_direct_debit/workflow/account_payment.xml 2013-01-02 14:45:02 +0000 |
3814 | +++ account_direct_debit/workflow/account_payment.xml 1970-01-01 00:00:00 +0000 |
3815 | @@ -1,25 +0,0 @@ |
3816 | -<?xml version="1.0" encoding="utf-8"?> |
3817 | -<openerp> |
3818 | - <data> |
3819 | - <!-- |
3820 | - Transition to undo the payment order and reset to |
3821 | - sent, triggered by |
3822 | - cancelling a bank transaction with which the order |
3823 | - was reconciled. |
3824 | - For this, we need to cancel the flow stop on the done state, |
3825 | - unfortunately. |
3826 | - TODO: what is below is not enough. We need to inject |
3827 | - another state, 'sent_wait' between sent and done. |
3828 | - --> |
3829 | - <record id="account_payment.act_done" model="workflow.activity"> |
3830 | - <field name="flow_stop" eval="False"/> |
3831 | - </record> |
3832 | - |
3833 | - <record id="trans_done_sent" model="workflow.transition"> |
3834 | - <field name="act_from" ref="account_payment.act_done"/> |
3835 | - <field name="act_to" ref="account_banking.act_sent"/> |
3836 | - <field name="condition">test_undo_done()</field> |
3837 | - <field name="signal">undo_done</field> |
3838 | - </record> |
3839 | - </data> |
3840 | -</openerp> |
3841 | |
3842 | === modified file 'account_payment_shortcut/__init__.py' |
3843 | --- account_payment_shortcut/__init__.py 2011-12-09 13:07:52 +0000 |
3844 | +++ account_payment_shortcut/__init__.py 2013-06-26 21:16:23 +0000 |
3845 | @@ -1,1 +1,2 @@ |
3846 | +# -*- coding: utf-8 -*- |
3847 | import payment_order |
3848 | |
3849 | === modified file 'account_payment_shortcut/payment_order.py' |
3850 | --- account_payment_shortcut/payment_order.py 2011-12-09 13:07:52 +0000 |
3851 | +++ account_payment_shortcut/payment_order.py 2013-06-26 21:16:23 +0000 |
3852 | @@ -1,8 +1,30 @@ |
3853 | # -*- coding: utf-8 -*- |
3854 | -from osv import osv, fields |
3855 | - |
3856 | -class payment_order_create(osv.osv_memory): |
3857 | - |
3858 | +############################################################################## |
3859 | +# |
3860 | +# Copyright (C) 2011 - 2013 Therp BV (<http://therp.nl>). |
3861 | +# |
3862 | +# All other contributions are (C) by their respective contributors |
3863 | +# |
3864 | +# All Rights Reserved |
3865 | +# |
3866 | +# This program is free software: you can redistribute it and/or modify |
3867 | +# it under the terms of the GNU Affero General Public License as |
3868 | +# published by the Free Software Foundation, either version 3 of the |
3869 | +# License, or (at your option) any later version. |
3870 | +# |
3871 | +# This program is distributed in the hope that it will be useful, |
3872 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3873 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
3874 | +# GNU Affero General Public License for more details. |
3875 | +# |
3876 | +# You should have received a copy of the GNU Affero General Public License |
3877 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
3878 | +# |
3879 | +############################################################################## |
3880 | + |
3881 | +from osv import orm |
3882 | + |
3883 | +class payment_order_create(orm.TransientModel): |
3884 | _inherit = 'payment.order.create' |
3885 | |
3886 | def default_get(self, cr, uid, fields_list, context=None): |
3887 | @@ -27,5 +49,3 @@ |
3888 | res['entries'] = context['line_ids'] |
3889 | |
3890 | return res |
3891 | - |
3892 | -payment_order_create() |
3893 | |
3894 | === modified file 'bank_statement_instant_voucher/model/account_bank_statement_line.py' |
3895 | --- bank_statement_instant_voucher/model/account_bank_statement_line.py 2012-12-05 20:16:14 +0000 |
3896 | +++ bank_statement_instant_voucher/model/account_bank_statement_line.py 2013-06-26 21:16:23 +0000 |
3897 | @@ -2,7 +2,7 @@ |
3898 | ############################################################################## |
3899 | # |
3900 | # OpenERP, Open Source Management Solution |
3901 | -# This module copyright (C) 2012 Therp BV (<http://therp.nl>). |
3902 | +# This module copyright (C) 2012 - 2013 Therp BV (<http://therp.nl>). |
3903 | # |
3904 | # This program is free software: you can redistribute it and/or modify |
3905 | # it under the terms of the GNU Affero General Public License as |
3906 | @@ -19,10 +19,10 @@ |
3907 | # |
3908 | ############################################################################## |
3909 | |
3910 | -from openerp.osv import osv, fields |
3911 | - |
3912 | - |
3913 | -class account_bank_statement_line(osv.Model): |
3914 | +from openerp.osv import orm, fields |
3915 | + |
3916 | + |
3917 | +class account_bank_statement_line(orm.Model): |
3918 | _inherit = 'account.bank.statement.line' |
3919 | def create_instant_voucher(self, cr, uid, ids, context=None): |
3920 | res = False |
3921 | |
3922 | === modified file 'bank_statement_instant_voucher/model/account_voucher_instant.py' |
3923 | --- bank_statement_instant_voucher/model/account_voucher_instant.py 2012-12-05 20:16:14 +0000 |
3924 | +++ bank_statement_instant_voucher/model/account_voucher_instant.py 2013-06-26 21:16:23 +0000 |
3925 | @@ -2,7 +2,7 @@ |
3926 | ############################################################################## |
3927 | # |
3928 | # OpenERP, Open Source Management Solution |
3929 | -# This module copyright (C) 2012 Therp BV (<http://therp.nl>). |
3930 | +# This module copyright (C) 2012 - 2013 Therp BV (<http://therp.nl>). |
3931 | # |
3932 | # This program is free software: you can redistribute it and/or modify |
3933 | # it under the terms of the GNU Affero General Public License as |
3934 | @@ -19,12 +19,12 @@ |
3935 | # |
3936 | ############################################################################## |
3937 | |
3938 | -from openerp.osv import osv, fields |
3939 | +from openerp.osv import orm, fields |
3940 | from openerp.tools.translate import _ |
3941 | from openerp.addons.decimal_precision import decimal_precision as dp |
3942 | |
3943 | |
3944 | -class instant_voucher(osv.TransientModel): |
3945 | +class instant_voucher(orm.TransientModel): |
3946 | _name = 'account.voucher.instant' |
3947 | _description = 'Instant Voucher' |
3948 | |
3949 | @@ -76,7 +76,7 @@ |
3950 | cr, uid, [('company_id', '=', line.company_id.id), |
3951 | ('type', '=', voucher_type)]) |
3952 | if not journal_ids: |
3953 | - osv.exept_osv( |
3954 | + orm.exept_orm( |
3955 | _('Error'), |
3956 | _('No %s journal defined') % voucher_type) |
3957 | |
3958 | @@ -156,7 +156,7 @@ |
3959 | context.get('active_id') or |
3960 | context.get('active_ids') and context.get('active_ids')[0]) |
3961 | if not res['statement_line_id']: |
3962 | - raise osv.except_osv( |
3963 | + raise orm.except_orm( |
3964 | _('Error'), |
3965 | _('Cannot determine statement line')) |
3966 | line = self.pool.get('account.bank.statement.line').browse( |
3967 | @@ -212,7 +212,7 @@ |
3968 | instant.voucher_id.company_id.currency_id) |
3969 | if (instant.statement_line_id.statement_id.currency.id != |
3970 | voucher_currency.id): |
3971 | - raise osv.except_osv( |
3972 | + raise orm.except_orm( |
3973 | _("Error"), |
3974 | _("Currency on the bank statement line needs to be the " |
3975 | "same as on the voucher. Currency conversion is not yet " |
3976 | @@ -222,7 +222,7 @@ |
3977 | cr, uid, [instant.voucher_id.id], context=context) |
3978 | instant.refresh() |
3979 | if instant.voucher_id.state != 'posted': |
3980 | - raise osv.except_osv( |
3981 | + raise orm.except_orm( |
3982 | _("Error"), |
3983 | _("The voucher could not be posted.")) |
3984 | if instant.voucher_id.move_id.state != 'posted': |
3985 | @@ -230,12 +230,12 @@ |
3986 | cr, uid, [instant.voucher_id.move_id.id], context=context) |
3987 | instant.refresh() |
3988 | if instant.voucher_id.move_id.state != 'posted': |
3989 | - raise osv.except_osv( |
3990 | + raise orm.except_orm( |
3991 | _("Error"), |
3992 | _("The voucher's move line could not be posted.")) |
3993 | if not self.pool.get('res.currency').is_zero( |
3994 | cr, uid, voucher_currency, instant.balance): |
3995 | - raise osv.except_osv( |
3996 | + raise orm.except_orm( |
3997 | _("Error"), |
3998 | _("The amount on the bank statement line needs to be the " |
3999 | "same as on the voucher. Write-off is not yet " |
4000 | @@ -245,7 +245,7 @@ |
4001 | # and trigger its posting and reconciliation. |
4002 | if 'import_transaction_id' in statement_line_obj._columns: |
4003 | if instant.statement_line_id.state == 'confirmed': |
4004 | - raise osv.except_osv( |
4005 | + raise orm.except_orm( |
4006 | _("Error"), |
4007 | _("Cannot match a confirmed statement line")) |
4008 | if not instant.statement_line_id.import_transaction_id: |
4009 | |
4010 | === modified file 'bank_statement_instant_voucher/view/account_bank_statement_line.xml' |
4011 | --- bank_statement_instant_voucher/view/account_bank_statement_line.xml 2012-11-28 13:49:36 +0000 |
4012 | +++ bank_statement_instant_voucher/view/account_bank_statement_line.xml 2013-06-26 21:16:23 +0000 |
4013 | @@ -5,7 +5,6 @@ |
4014 | <field name="name">Add instant voucher button to bank statement line on statement form</field> |
4015 | <field name="inherit_id" ref="account.view_bank_statement_form" /> |
4016 | <field name="model">account.bank.statement</field> |
4017 | - <field name="type">form</field> |
4018 | <field name="priority" eval="30"/> |
4019 | <field name="arch" type="xml"> |
4020 | <xpath expr="/form/notebook/page/field[@name='line_ids']/tree/field[@name='voucher_id']" |
4021 | |
4022 | === modified file 'bank_statement_instant_voucher/view/account_voucher_instant.xml' |
4023 | --- bank_statement_instant_voucher/view/account_voucher_instant.xml 2012-11-28 13:49:36 +0000 |
4024 | +++ bank_statement_instant_voucher/view/account_voucher_instant.xml 2013-06-26 21:16:23 +0000 |
4025 | @@ -4,7 +4,6 @@ |
4026 | <record id="instant_voucher_form" model="ir.ui.view"> |
4027 | <field name="name">Instant voucher form view</field> |
4028 | <field name="model">account.voucher.instant</field> |
4029 | - <field name="type">form</field> |
4030 | <field name="arch" type="xml"> |
4031 | <form> |
4032 | <field name="state" invisible="1" readonly="1"/> |
just a few small things, approving anyways:
#102 maybe use the opportunity to make this function contaxt-aware? move_line_ id?
#140ff same with passing context in the onchange_functions
#550 570, 880 considering how often you use this selection, you should move it to its own field. This also simplifies adjusting the selection
#1591 check if there are line_ids
#1682 should be translated
#1692 too
#1784 why can we drop this check? shouldn't it be changed to check for transit_
Could you elaborate on the sent_wait state? If it's meant how I think it is, such a migration seems not necessary to me.