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