Merge lp:~therp-nl/banking-addons/6.1-link_partner_wizard into lp:banking-addons/6.1
- 6.1-link_partner_wizard
- Merge into 6.1
Proposed by
Stefan Rijnhart (Opener)
Status: | Merged |
---|---|
Merged at revision: | 169 |
Proposed branch: | lp:~therp-nl/banking-addons/6.1-link_partner_wizard |
Merge into: | lp:banking-addons/6.1 |
Diff against target: |
719 lines (+391/-110) 8 files modified
account_banking/__openerp__.py (+1/-0) account_banking/account_banking_view.xml (+14/-0) account_banking/banking_import_transaction.py (+103/-35) account_banking/wizard/__init__.py (+1/-0) account_banking/wizard/banking_transaction_wizard.py (+3/-3) account_banking/wizard/banktools.py (+65/-72) account_banking/wizard/link_partner.py (+157/-0) account_banking/wizard/link_partner.xml (+47/-0) |
To merge this branch: | bzr merge lp:~therp-nl/banking-addons/6.1-link_partner_wizard |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Holger Brunn (Therp) | code review, no test | Approve | |
Guewen Baconnier @ Camptocamp | code review, no test | Approve | |
Review via email:
|
Commit message
Description of the change
To post a comment you must log in.
- 166. By Stefan Rijnhart (Opener)
-
[FIX] Adapt to API change in last commit
- 167. By Stefan Rijnhart (Opener)
-
[FIX] Declare wizard as a TransientModel, not Model
- 168. By Stefan Rijnhart (Opener)
-
[FIX] Boolean function field not to return browse_null record
Revision history for this message

Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
review:
Needs Fixing
(code review, no test)
- 169. By Stefan Rijnhart (Opener)
-
[FIX] Address is created without partner
- 170. By Stefan Rijnhart (Opener)
-
[FIX] Undefined variables
[FIX] Check ids for long type, not float
[FIX] Prevent extra indentation level by early return
Revision history for this message

Stefan Rijnhart (Opener) (stefan-opener) wrote : | # |
Thanks Guewen, I implemented your suggestions. The float thing was a copy paste error. I corrected every other occurrence as well.
Revision history for this message

Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
Looks good to me, thanks for the changes.
review:
Approve
(code review, no test)
Revision history for this message

Holger Brunn (Therp) (hbrunn) : | # |
review:
Approve
(code review, no test)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'account_banking/__openerp__.py' | |||
2 | --- account_banking/__openerp__.py 2012-05-07 11:49:08 +0000 | |||
3 | +++ account_banking/__openerp__.py 2013-04-29 08:25:30 +0000 | |||
4 | @@ -45,6 +45,7 @@ | |||
5 | 45 | 'account_banking_view.xml', | 45 | 'account_banking_view.xml', |
6 | 46 | 'account_banking_workflow.xml', | 46 | 'account_banking_workflow.xml', |
7 | 47 | 'wizard/banking_transaction_wizard.xml', | 47 | 'wizard/banking_transaction_wizard.xml', |
8 | 48 | 'wizard/link_partner.xml', | ||
9 | 48 | 'workflow/account_invoice.xml', | 49 | 'workflow/account_invoice.xml', |
10 | 49 | ], | 50 | ], |
11 | 50 | 'demo_xml': [], | 51 | 'demo_xml': [], |
12 | 51 | 52 | ||
13 | === modified file 'account_banking/account_banking_view.xml' | |||
14 | --- account_banking/account_banking_view.xml 2013-04-25 08:15:21 +0000 | |||
15 | +++ account_banking/account_banking_view.xml 2013-04-29 08:25:30 +0000 | |||
16 | @@ -286,6 +286,13 @@ | |||
17 | 286 | <field name="arch" type="xml"> | 286 | <field name="arch" type="xml"> |
18 | 287 | <data> | 287 | <data> |
19 | 288 | <xpath expr="/form/notebook/page/field[@name='line_ids']/tree/field[@name='partner_id']" position="after"> | 288 | <xpath expr="/form/notebook/page/field[@name='line_ids']/tree/field[@name='partner_id']" position="after"> |
20 | 289 | <field name="link_partner_ok" invisible="1" /> | ||
21 | 290 | <button name="link_partner" | ||
22 | 291 | string="Link partner" | ||
23 | 292 | icon="terp-partner" | ||
24 | 293 | type="object" | ||
25 | 294 | attrs="{'invisible': [('link_partner_ok', '=', False)]}" | ||
26 | 295 | /> | ||
27 | 289 | <!-- TODO set partner_id when partner_bank_id changes --> | 296 | <!-- TODO set partner_id when partner_bank_id changes --> |
28 | 290 | <field name="partner_bank_id"/> | 297 | <field name="partner_bank_id"/> |
29 | 291 | </xpath> | 298 | </xpath> |
30 | @@ -514,6 +521,13 @@ | |||
31 | 514 | <field name="name"/> | 521 | <field name="name"/> |
32 | 515 | <field name="ref"/> | 522 | <field name="ref"/> |
33 | 516 | <field name="partner_id" on_change="onchange_partner_id(partner_id)"/> | 523 | <field name="partner_id" on_change="onchange_partner_id(partner_id)"/> |
34 | 524 | <field name="link_partner_ok" invisible="1" /> | ||
35 | 525 | <button name="link_partner" | ||
36 | 526 | string="Link partner" | ||
37 | 527 | icon="terp-partner" | ||
38 | 528 | type="object" | ||
39 | 529 | attrs="{'invisible': [('link_partner_ok', '=', False)]}" | ||
40 | 530 | /> | ||
41 | 517 | <!-- TODO set partner_id when partner_bank_id changes --> | 531 | <!-- TODO set partner_id when partner_bank_id changes --> |
42 | 518 | <field name="partner_bank_id"/> | 532 | <field name="partner_bank_id"/> |
43 | 519 | <field name="type" on_change="onchange_type(partner_id, type)"/> | 533 | <field name="type" on_change="onchange_type(partner_id, type)"/> |
44 | 520 | 534 | ||
45 | === modified file 'account_banking/banking_import_transaction.py' | |||
46 | --- account_banking/banking_import_transaction.py 2013-04-26 08:27:33 +0000 | |||
47 | +++ account_banking/banking_import_transaction.py 2013-04-29 08:25:30 +0000 | |||
48 | @@ -1134,6 +1134,9 @@ | |||
49 | 1134 | i += 1 | 1134 | i += 1 |
50 | 1135 | continue | 1135 | continue |
51 | 1136 | 1136 | ||
52 | 1137 | partner_banks = [] | ||
53 | 1138 | partner_ids = [] | ||
54 | 1139 | |||
55 | 1137 | # TODO: optimize by ordering transactions per company, | 1140 | # TODO: optimize by ordering transactions per company, |
56 | 1138 | # and perform the stanza below only once per company. | 1141 | # and perform the stanza below only once per company. |
57 | 1139 | # In that case, take newest transaction date into account | 1142 | # In that case, take newest transaction date into account |
58 | @@ -1277,6 +1280,7 @@ | |||
59 | 1277 | if transaction.type == bt.STORNO: | 1280 | if transaction.type == bt.STORNO: |
60 | 1278 | move_info = self._match_storno( | 1281 | move_info = self._match_storno( |
61 | 1279 | cr, uid, transaction, results['log'], context) | 1282 | cr, uid, transaction, results['log'], context) |
62 | 1283 | |||
63 | 1280 | # Allow inclusion of generated bank invoices | 1284 | # Allow inclusion of generated bank invoices |
64 | 1281 | if transaction.type == bt.BANK_COSTS: | 1285 | if transaction.type == bt.BANK_COSTS: |
65 | 1282 | lines = self._match_costs( | 1286 | lines = self._match_costs( |
66 | @@ -1288,7 +1292,6 @@ | |||
67 | 1288 | if not [x for x in move_lines if x.id == line.id]: | 1292 | if not [x for x in move_lines if x.id == line.id]: |
68 | 1289 | move_lines.append(line) | 1293 | move_lines.append(line) |
69 | 1290 | partner_ids = [account_info.bank_partner_id.id] | 1294 | partner_ids = [account_info.bank_partner_id.id] |
70 | 1291 | partner_banks = [] | ||
71 | 1292 | else: | 1295 | else: |
72 | 1293 | # Link remote partner, import account when needed | 1296 | # Link remote partner, import account when needed |
73 | 1294 | partner_banks = get_bank_accounts( | 1297 | partner_banks = get_bank_accounts( |
74 | @@ -1298,44 +1301,28 @@ | |||
75 | 1298 | if partner_banks: | 1301 | if partner_banks: |
76 | 1299 | partner_ids = [x.partner_id.id for x in partner_banks] | 1302 | partner_ids = [x.partner_id.id for x in partner_banks] |
77 | 1300 | elif transaction.remote_owner: | 1303 | elif transaction.remote_owner: |
91 | 1301 | iban = sepa.IBAN(transaction.remote_account) | 1304 | country_id = get_country_id( |
92 | 1302 | if iban.valid: | 1305 | self.pool, cr, uid, transaction, context=context) |
93 | 1303 | country_code = iban.countrycode | 1306 | partner_id = get_partner( |
81 | 1304 | elif transaction.remote_owner_country_code: | ||
82 | 1305 | country_code = transaction.remote_owner_country_code | ||
83 | 1306 | # fallback on the import parsers country code | ||
84 | 1307 | elif transaction.bank_country_code: | ||
85 | 1308 | country_code = transaction.bank_country_code | ||
86 | 1309 | elif company.partner_id and company.partner_id.country: | ||
87 | 1310 | country_code = company.partner_id.country.code | ||
88 | 1311 | else: | ||
89 | 1312 | country_code = None | ||
90 | 1313 | partner_id = get_or_create_partner( | ||
94 | 1314 | self.pool, cr, uid, transaction.remote_owner, | 1307 | self.pool, cr, uid, transaction.remote_owner, |
95 | 1315 | transaction.remote_owner_address, | 1308 | transaction.remote_owner_address, |
96 | 1316 | transaction.remote_owner_postalcode, | 1309 | transaction.remote_owner_postalcode, |
97 | 1317 | transaction.remote_owner_city, | 1310 | transaction.remote_owner_city, |
119 | 1318 | country_code, results['log'], context=context) | 1311 | country_id, results['log'], context=context) |
120 | 1319 | if transaction.remote_account: | 1312 | if partner_id: |
121 | 1320 | partner_bank_id = create_bank_account( | 1313 | partner_ids = [partner_id] |
122 | 1321 | self.pool, cr, uid, partner_id, | 1314 | if transaction.remote_account: |
123 | 1322 | transaction.remote_account, | 1315 | partner_bank_id = create_bank_account( |
124 | 1323 | transaction.remote_owner, | 1316 | self.pool, cr, uid, partner_id, |
125 | 1324 | transaction.remote_owner_address, | 1317 | transaction.remote_account, |
126 | 1325 | transaction.remote_owner_city, | 1318 | transaction.remote_owner, |
127 | 1326 | country_code, results['log'], | 1319 | transaction.remote_owner_address, |
128 | 1327 | bic=transaction.remote_bank_bic | 1320 | transaction.remote_owner_city, |
129 | 1328 | ) | 1321 | country_id, bic=transaction.remote_bank_bic, |
130 | 1329 | partner_banks = partner_bank_obj.browse( | 1322 | ) |
131 | 1330 | cr, uid, [partner_bank_id] | 1323 | partner_banks = partner_bank_obj.browse( |
132 | 1331 | ) | 1324 | cr, uid, [partner_bank_id] |
133 | 1332 | else: | 1325 | ) |
113 | 1333 | partner_bank_id = None | ||
114 | 1334 | partner_banks = [] | ||
115 | 1335 | partner_ids = [partner_id] | ||
116 | 1336 | else: | ||
117 | 1337 | partner_ids = [] | ||
118 | 1338 | partner_banks = [] | ||
134 | 1339 | 1326 | ||
135 | 1340 | # Credit means payment... isn't it? | 1327 | # Credit means payment... isn't it? |
136 | 1341 | if (not move_info | 1328 | if (not move_info |
137 | @@ -1706,6 +1693,24 @@ | |||
138 | 1706 | 1693 | ||
139 | 1707 | class account_bank_statement_line(osv.osv): | 1694 | class account_bank_statement_line(osv.osv): |
140 | 1708 | _inherit = 'account.bank.statement.line' | 1695 | _inherit = 'account.bank.statement.line' |
141 | 1696 | |||
142 | 1697 | def _get_link_partner_ok( | ||
143 | 1698 | self, cr, uid, ids, name, args, context=None): | ||
144 | 1699 | """ | ||
145 | 1700 | Deliver the values of the function field that | ||
146 | 1701 | determines if the 'link partner' wizard is show on the | ||
147 | 1702 | bank statement line | ||
148 | 1703 | """ | ||
149 | 1704 | res = {} | ||
150 | 1705 | for line in self.browse(cr, uid, ids, context): | ||
151 | 1706 | res[line.id] = bool( | ||
152 | 1707 | line.state == 'draft' | ||
153 | 1708 | and not line.partner_id | ||
154 | 1709 | and line.import_transaction_id | ||
155 | 1710 | and line.import_transaction_id.remote_owner | ||
156 | 1711 | and line.import_transaction_id.remote_account) | ||
157 | 1712 | return res | ||
158 | 1713 | |||
159 | 1709 | _columns = { | 1714 | _columns = { |
160 | 1710 | 'import_transaction_id': fields.many2one( | 1715 | 'import_transaction_id': fields.many2one( |
161 | 1711 | 'banking.import.transaction', | 1716 | 'banking.import.transaction', |
162 | @@ -1730,6 +1735,9 @@ | |||
163 | 1730 | 'state': fields.selection( | 1735 | 'state': fields.selection( |
164 | 1731 | [('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State', | 1736 | [('draft', 'Draft'), ('confirmed', 'Confirmed')], 'State', |
165 | 1732 | readonly=True, required=True), | 1737 | readonly=True, required=True), |
166 | 1738 | 'link_partner_ok': fields.function( | ||
167 | 1739 | _get_link_partner_ok, type='boolean', | ||
168 | 1740 | string='Can link partner'), | ||
169 | 1733 | } | 1741 | } |
170 | 1734 | 1742 | ||
171 | 1735 | _defaults = { | 1743 | _defaults = { |
172 | @@ -1750,6 +1758,66 @@ | |||
173 | 1750 | res = wizard_obj.create_act_window(cr, uid, res_id, context=context) | 1758 | res = wizard_obj.create_act_window(cr, uid, res_id, context=context) |
174 | 1751 | return res | 1759 | return res |
175 | 1752 | 1760 | ||
176 | 1761 | def link_partner(self, cr, uid, ids, context=None): | ||
177 | 1762 | """ | ||
178 | 1763 | Get the appropriate partner or fire a wizard to create | ||
179 | 1764 | or link one | ||
180 | 1765 | """ | ||
181 | 1766 | if not ids: | ||
182 | 1767 | return False | ||
183 | 1768 | |||
184 | 1769 | if isinstance(ids, (int, long)): | ||
185 | 1770 | ids = [ids] | ||
186 | 1771 | |||
187 | 1772 | # Check if the partner is already known but not shown | ||
188 | 1773 | # because the screen was not refreshed yet | ||
189 | 1774 | statement_line = self.browse( | ||
190 | 1775 | cr, uid, ids[0], context=context) | ||
191 | 1776 | if statement_line.partner_id: | ||
192 | 1777 | return True | ||
193 | 1778 | |||
194 | 1779 | # Reuse the bank's partner if any | ||
195 | 1780 | if (statement_line.partner_bank_id and | ||
196 | 1781 | statement_line.partner_bank_id.partner_id): | ||
197 | 1782 | statement_line.write( | ||
198 | 1783 | {'partner_id': statement_line.partner_bank_id.partner_id.id}) | ||
199 | 1784 | return True | ||
200 | 1785 | |||
201 | 1786 | if (not statement_line.import_transaction_id or | ||
202 | 1787 | not statement_line.import_transaction_id.remote_account): | ||
203 | 1788 | raise osv.except_osv( | ||
204 | 1789 | _("Error"), | ||
205 | 1790 | _("No bank account available to link partner to")) | ||
206 | 1791 | |||
207 | 1792 | # Check if the bank account was already been linked | ||
208 | 1793 | # manually to another transaction | ||
209 | 1794 | remote_account = statement_line.import_transaction_id.remote_account | ||
210 | 1795 | source_line_ids = self.search( | ||
211 | 1796 | cr, uid, | ||
212 | 1797 | [('import_transaction_id.remote_account', '=', remote_account), | ||
213 | 1798 | ('partner_bank_id.partner_id', '!=', False), | ||
214 | 1799 | ], limit=1, context=context) | ||
215 | 1800 | if source_line_ids: | ||
216 | 1801 | source_line = self.browse( | ||
217 | 1802 | cr, uid, source_line_ids[0], context=context) | ||
218 | 1803 | target_line_ids = self.search( | ||
219 | 1804 | cr, uid, | ||
220 | 1805 | [('import_transaction_id.remote_account', '=', remote_account), | ||
221 | 1806 | ('partner_bank_id', '=', False), | ||
222 | 1807 | ('state', '=', 'draft')], context=context) | ||
223 | 1808 | self.write( | ||
224 | 1809 | cr, uid, target_line_ids, | ||
225 | 1810 | {'partner_bank_id': source_line.partner_bank_id.id, | ||
226 | 1811 | 'partner_id': source_line.partner_bank_id.partner_id.id, | ||
227 | 1812 | }, context=context) | ||
228 | 1813 | return True | ||
229 | 1814 | |||
230 | 1815 | # Or fire the wizard to link partner and account | ||
231 | 1816 | wizard_obj = self.pool.get('banking.link_partner') | ||
232 | 1817 | res_id = wizard_obj.create( | ||
233 | 1818 | cr, uid, {'statement_line_id': ids[0]}, context=context) | ||
234 | 1819 | return wizard_obj.create_act_window(cr, uid, res_id, context=context) | ||
235 | 1820 | |||
236 | 1753 | def _convert_currency( | 1821 | def _convert_currency( |
237 | 1754 | self, cr, uid, from_curr_id, to_curr_id, from_amount, | 1822 | self, cr, uid, from_curr_id, to_curr_id, from_amount, |
238 | 1755 | round=False, date=None, context=None): | 1823 | round=False, date=None, context=None): |
239 | 1756 | 1824 | ||
240 | === modified file 'account_banking/wizard/__init__.py' | |||
241 | --- account_banking/wizard/__init__.py 2011-12-19 12:03:32 +0000 | |||
242 | +++ account_banking/wizard/__init__.py 2013-04-29 08:25:30 +0000 | |||
243 | @@ -22,5 +22,6 @@ | |||
244 | 22 | import bank_payment_manual | 22 | import bank_payment_manual |
245 | 23 | import account_payment_order | 23 | import account_payment_order |
246 | 24 | import banking_transaction_wizard | 24 | import banking_transaction_wizard |
247 | 25 | import link_partner | ||
248 | 25 | 26 | ||
249 | 26 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | 27 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
250 | 27 | 28 | ||
251 | === modified file 'account_banking/wizard/banking_transaction_wizard.py' | |||
252 | --- account_banking/wizard/banking_transaction_wizard.py 2012-12-01 18:31:34 +0000 | |||
253 | +++ account_banking/wizard/banking_transaction_wizard.py 2013-04-29 08:25:30 +0000 | |||
254 | @@ -71,7 +71,7 @@ | |||
255 | 71 | Call the automatic matching routine for one or | 71 | Call the automatic matching routine for one or |
256 | 72 | more bank transactions | 72 | more bank transactions |
257 | 73 | """ | 73 | """ |
259 | 74 | if isinstance(ids, (int, float)): | 74 | if isinstance(ids, (int, long)): |
260 | 75 | ids = [ids] | 75 | ids = [ids] |
261 | 76 | import_transaction_obj = self.pool.get('banking.import.transaction') | 76 | import_transaction_obj = self.pool.get('banking.import.transaction') |
262 | 77 | trans_id = self.read( | 77 | trans_id = self.read( |
263 | @@ -231,7 +231,7 @@ | |||
264 | 231 | settings_pool = self.pool.get('account.banking.account.settings') | 231 | settings_pool = self.pool.get('account.banking.account.settings') |
265 | 232 | statement_pool = self.pool.get('account.bank.statement.line') | 232 | statement_pool = self.pool.get('account.bank.statement.line') |
266 | 233 | 233 | ||
268 | 234 | if isinstance(ids, (int, float)): | 234 | if isinstance(ids, (int, long)): |
269 | 235 | ids = [ids] | 235 | ids = [ids] |
270 | 236 | 236 | ||
271 | 237 | for wiz in self.browse(cr, uid, ids, context=context): | 237 | for wiz in self.browse(cr, uid, ids, context=context): |
272 | @@ -258,7 +258,7 @@ | |||
273 | 258 | return True | 258 | return True |
274 | 259 | 259 | ||
275 | 260 | def reverse_duplicate(self, cr, uid, ids, context=None): | 260 | def reverse_duplicate(self, cr, uid, ids, context=None): |
277 | 261 | if isinstance(ids, (int, float)): | 261 | if isinstance(ids, (int, long)): |
278 | 262 | ids = [ids] | 262 | ids = [ids] |
279 | 263 | transaction_obj = self.pool.get('banking.import.transaction') | 263 | transaction_obj = self.pool.get('banking.import.transaction') |
280 | 264 | for wiz in self.read( | 264 | for wiz in self.read( |
281 | 265 | 265 | ||
282 | === modified file 'account_banking/wizard/banktools.py' | |||
283 | --- account_banking/wizard/banktools.py 2013-02-07 09:38:41 +0000 | |||
284 | +++ account_banking/wizard/banktools.py 2013-04-29 08:25:30 +0000 | |||
285 | @@ -28,7 +28,8 @@ | |||
286 | 28 | __all__ = [ | 28 | __all__ = [ |
287 | 29 | 'get_period', | 29 | 'get_period', |
288 | 30 | 'get_bank_accounts', | 30 | 'get_bank_accounts', |
290 | 31 | 'get_or_create_partner', | 31 | 'get_partner', |
291 | 32 | 'get_country_id', | ||
292 | 32 | 'get_company_bank_account', | 33 | 'get_company_bank_account', |
293 | 33 | 'create_bank_account', | 34 | 'create_bank_account', |
294 | 34 | ] | 35 | ] |
295 | @@ -89,7 +90,7 @@ | |||
296 | 89 | ''' | 90 | ''' |
297 | 90 | # No need to search for nothing | 91 | # No need to search for nothing |
298 | 91 | if not account_number: | 92 | if not account_number: |
300 | 92 | return False | 93 | return [] |
301 | 93 | 94 | ||
302 | 94 | partner_bank_obj = pool.get('res.partner.bank') | 95 | partner_bank_obj = pool.get('res.partner.bank') |
303 | 95 | bank_account_ids = partner_bank_obj.search(cursor, uid, [ | 96 | bank_account_ids = partner_bank_obj.search(cursor, uid, [ |
304 | @@ -107,7 +108,7 @@ | |||
305 | 107 | _('Bank account %(account_no)s was not found in the database') | 108 | _('Bank account %(account_no)s was not found in the database') |
306 | 108 | % dict(account_no=account_number) | 109 | % dict(account_no=account_number) |
307 | 109 | ) | 110 | ) |
309 | 110 | return False | 111 | return [] |
310 | 111 | return partner_bank_obj.browse(cursor, uid, bank_account_ids) | 112 | return partner_bank_obj.browse(cursor, uid, bank_account_ids) |
311 | 112 | 113 | ||
312 | 113 | def _has_attr(obj, attr): | 114 | def _has_attr(obj, attr): |
313 | @@ -118,10 +119,10 @@ | |||
314 | 118 | except KeyError: | 119 | except KeyError: |
315 | 119 | return False | 120 | return False |
316 | 120 | 121 | ||
319 | 121 | def get_or_create_partner(pool, cr, uid, name, address, postal_code, city, | 122 | def get_partner(pool, cr, uid, name, address, postal_code, city, |
320 | 122 | country_code, log, context=None): | 123 | country_id, log, context=None): |
321 | 123 | ''' | 124 | ''' |
323 | 124 | Get or create the partner belonging to the account holders name <name> | 125 | Get the partner belonging to the account holders name <name> |
324 | 125 | 126 | ||
325 | 126 | If multiple partners are found with the same name, select the first and | 127 | If multiple partners are found with the same name, select the first and |
326 | 127 | add a warning to the import log. | 128 | add a warning to the import log. |
327 | @@ -131,16 +132,10 @@ | |||
328 | 131 | partner_obj = pool.get('res.partner') | 132 | partner_obj = pool.get('res.partner') |
329 | 132 | partner_ids = partner_obj.search(cr, uid, [('name', 'ilike', name)], | 133 | partner_ids = partner_obj.search(cr, uid, [('name', 'ilike', name)], |
330 | 133 | context=context) | 134 | context=context) |
331 | 134 | country_id = False | ||
332 | 135 | if not partner_ids: | 135 | if not partner_ids: |
333 | 136 | # Try brute search on address and then match reverse | 136 | # Try brute search on address and then match reverse |
334 | 137 | criteria = [] | 137 | criteria = [] |
341 | 138 | if country_code: | 138 | if country_id: |
336 | 139 | country_obj = pool.get('res.country') | ||
337 | 140 | country_ids = country_obj.search( | ||
338 | 141 | cr, uid, [('code', '=', country_code.upper())], | ||
339 | 142 | context=context) | ||
340 | 143 | country_id = country_ids and country_ids[0] or False | ||
342 | 144 | criteria.append(('address.country_id', '=', country_id)) | 139 | criteria.append(('address.country_id', '=', country_id)) |
343 | 145 | if city: | 140 | if city: |
344 | 146 | criteria.append(('address.city', 'ilike', city)) | 141 | criteria.append(('address.city', 'ilike', city)) |
345 | @@ -148,6 +143,11 @@ | |||
346 | 148 | criteria.append(('address.zip', 'ilike', postal_code)) | 143 | criteria.append(('address.zip', 'ilike', postal_code)) |
347 | 149 | partner_search_ids = partner_obj.search( | 144 | partner_search_ids = partner_obj.search( |
348 | 150 | cr, uid, criteria, context=context) | 145 | cr, uid, criteria, context=context) |
349 | 146 | if (not partner_search_ids and country_id): | ||
350 | 147 | # Try again with country_id = False | ||
351 | 148 | criteria[0] = ('address.country_id', '=', False) | ||
352 | 149 | partner_search_ids = partner_obj.search( | ||
353 | 150 | cr, uid, criteria, context=context) | ||
354 | 151 | key = name.lower() | 151 | key = name.lower() |
355 | 152 | partners = [] | 152 | partners = [] |
356 | 153 | for partner in partner_obj.read( | 153 | for partner in partner_obj.read( |
357 | @@ -156,31 +156,11 @@ | |||
358 | 156 | partners.append(partner) | 156 | partners.append(partner) |
359 | 157 | partners.sort(key=lambda x: len(x['name']), reverse=True) | 157 | partners.sort(key=lambda x: len(x['name']), reverse=True) |
360 | 158 | partner_ids = [x['id'] for x in partners] | 158 | partner_ids = [x['id'] for x in partners] |
386 | 159 | if not partner_ids: | 159 | if len(partner_ids) > 1: |
387 | 160 | if not country_id: | 160 | log.append( |
388 | 161 | user = pool.get('res.user').browse(cr, uid, uid, context=context) | 161 | _('More than one possible match found for partner with ' |
389 | 162 | country_id = ( | 162 | 'name %(name)s') % {'name': name}) |
390 | 163 | user.company_id.partner_id.country and | 163 | return partner_ids and partner_ids[0] or False |
366 | 164 | user.company_id.partner_id.country.id or | ||
367 | 165 | False | ||
368 | 166 | ) | ||
369 | 167 | partner_id = partner_obj.create(cr, uid, dict( | ||
370 | 168 | name=name, active=True, | ||
371 | 169 | comment='Generated from Bank Statements Import', | ||
372 | 170 | address=[(0,0,{ | ||
373 | 171 | 'street': address and address[0] or '', | ||
374 | 172 | 'street2': len(address) > 1 and address[1] or '', | ||
375 | 173 | 'city': city, | ||
376 | 174 | 'zip': postal_code or '', | ||
377 | 175 | 'country_id': country_id, | ||
378 | 176 | })]), context=context) | ||
379 | 177 | else: | ||
380 | 178 | if len(partner_ids) > 1: | ||
381 | 179 | log.append( | ||
382 | 180 | _('More than one possible match found for partner with ' | ||
383 | 181 | 'name %(name)s') % {'name': name}) | ||
384 | 182 | partner_id = partner_ids[0] | ||
385 | 183 | return partner_id | ||
391 | 184 | 164 | ||
392 | 185 | def get_company_bank_account(pool, cursor, uid, account_number, currency, | 165 | def get_company_bank_account(pool, cursor, uid, account_number, currency, |
393 | 186 | company, log): | 166 | company, log): |
394 | @@ -311,19 +291,47 @@ | |||
395 | 311 | )) | 291 | )) |
396 | 312 | return bank_id, country_id | 292 | return bank_id, country_id |
397 | 313 | 293 | ||
399 | 314 | def create_bank_account(pool, cursor, uid, partner_id, | 294 | def get_country_id(pool, cr, uid, transaction, context=None): |
400 | 295 | """ | ||
401 | 296 | Derive a country id from the info on the transaction. | ||
402 | 297 | |||
403 | 298 | :param transaction: browse record of a transaction | ||
404 | 299 | :returns: res.country id or False | ||
405 | 300 | """ | ||
406 | 301 | |||
407 | 302 | country_code = False | ||
408 | 303 | iban = sepa.IBAN(transaction.remote_account) | ||
409 | 304 | if iban.valid: | ||
410 | 305 | country_code = iban.countrycode | ||
411 | 306 | elif transaction.remote_owner_country_code: | ||
412 | 307 | country_code = transaction.remote_owner_country_code | ||
413 | 308 | # fallback on the import parsers country code | ||
414 | 309 | elif transaction.bank_country_code: | ||
415 | 310 | country_code = transaction.bank_country_code | ||
416 | 311 | if country_code: | ||
417 | 312 | country_ids = pool.get('res.country').search( | ||
418 | 313 | cr, uid, [('code', '=', country_code.upper())], | ||
419 | 314 | context=context) | ||
420 | 315 | country_id = country_ids and country_ids[0] or False | ||
421 | 316 | if not country_id: | ||
422 | 317 | company = transaction.statement_line_id.company_id | ||
423 | 318 | if company.partner_id.country: | ||
424 | 319 | country_id = company.partner_id.country.id | ||
425 | 320 | return country_id | ||
426 | 321 | |||
427 | 322 | def create_bank_account(pool, cr, uid, partner_id, | ||
428 | 315 | account_number, holder_name, address, city, | 323 | account_number, holder_name, address, city, |
431 | 316 | country_code, log, bic=False, | 324 | country_id, bic=False, |
432 | 317 | ): | 325 | context=None): |
433 | 318 | ''' | 326 | ''' |
434 | 319 | Create a matching bank account with this holder for this partner. | 327 | Create a matching bank account with this holder for this partner. |
435 | 320 | ''' | 328 | ''' |
436 | 321 | values = struct( | 329 | values = struct( |
437 | 322 | partner_id = partner_id, | 330 | partner_id = partner_id, |
438 | 323 | owner_name = holder_name, | 331 | owner_name = holder_name, |
439 | 332 | country_id = country_id, | ||
440 | 324 | ) | 333 | ) |
441 | 325 | bankcode = None | 334 | bankcode = None |
442 | 326 | country_obj = pool.get('res.country') | ||
443 | 327 | 335 | ||
444 | 328 | # Are we dealing with IBAN? | 336 | # Are we dealing with IBAN? |
445 | 329 | iban = sepa.IBAN(account_number) | 337 | iban = sepa.IBAN(account_number) |
446 | @@ -333,44 +341,29 @@ | |||
447 | 333 | values.acc_number = str(iban) | 341 | values.acc_number = str(iban) |
448 | 334 | values.acc_number_domestic = iban.BBAN | 342 | values.acc_number_domestic = iban.BBAN |
449 | 335 | bankcode = iban.bankcode + iban.countrycode | 343 | bankcode = iban.bankcode + iban.countrycode |
450 | 336 | country_code = iban.countrycode | ||
451 | 337 | |||
452 | 338 | if not country_code: | ||
453 | 339 | country = pool.get('res.partner').browse( | ||
454 | 340 | cursor, uid, partner_id).country | ||
455 | 341 | country_code = country.code | ||
456 | 342 | country_id = country.id | ||
457 | 343 | else: | 344 | else: |
458 | 344 | if iban.valid: | ||
459 | 345 | country_ids = country_obj.search(cursor, uid, | ||
460 | 346 | [('code', '=', iban.countrycode)] | ||
461 | 347 | ) | ||
462 | 348 | else: | ||
463 | 349 | country_ids = country_obj.search(cursor, uid, | ||
464 | 350 | [('code', '=', country_code)] | ||
465 | 351 | ) | ||
466 | 352 | country_id = country_ids[0] | ||
467 | 353 | |||
468 | 354 | account_info = False | ||
469 | 355 | if not iban.valid: | ||
470 | 356 | # No, try to convert to IBAN | 345 | # No, try to convert to IBAN |
471 | 357 | values.state = 'bank' | 346 | values.state = 'bank' |
472 | 358 | values.acc_number = values.acc_number_domestic = account_number | 347 | values.acc_number = values.acc_number_domestic = account_number |
482 | 359 | if country_code in sepa.IBAN.countries: | 348 | |
483 | 360 | account_info = sepa.online.account_info(country_code, | 349 | if country_id: |
484 | 361 | values.acc_number | 350 | country_code = pool.get('res.country').read( |
485 | 362 | ) | 351 | cr, uid, country_id, ['code'], context=context)['code'] |
486 | 363 | if account_info: | 352 | if country_code in sepa.IBAN.countries: |
487 | 364 | values.acc_number = iban = account_info.iban | 353 | account_info = sepa.online.account_info( |
488 | 365 | values.state = 'iban' | 354 | country_code, values.acc_number) |
489 | 366 | bankcode = account_info.code | 355 | if account_info: |
490 | 367 | bic = account_info.bic | 356 | values.acc_number = iban = account_info.iban |
491 | 357 | values.state = 'iban' | ||
492 | 358 | bankcode = account_info.code | ||
493 | 359 | bic = account_info.bic | ||
494 | 368 | 360 | ||
495 | 369 | if bic: | 361 | if bic: |
497 | 370 | values.bank = get_or_create_bank(pool, cursor, uid, bic)[0] | 362 | values.bank = get_or_create_bank(pool, cr, uid, bic)[0] |
498 | 371 | values.bank_bic = bic | 363 | values.bank_bic = bic |
499 | 372 | 364 | ||
500 | 373 | # Create bank account and return | 365 | # Create bank account and return |
502 | 374 | return pool.get('res.partner.bank').create(cursor, uid, values) | 366 | return pool.get('res.partner.bank').create( |
503 | 367 | cr, uid, values, context=context) | ||
504 | 375 | 368 | ||
505 | 376 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: | 369 | # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
506 | 377 | 370 | ||
507 | === added file 'account_banking/wizard/link_partner.py' | |||
508 | --- account_banking/wizard/link_partner.py 1970-01-01 00:00:00 +0000 | |||
509 | +++ account_banking/wizard/link_partner.py 2013-04-29 08:25:30 +0000 | |||
510 | @@ -0,0 +1,157 @@ | |||
511 | 1 | # -*- coding: utf-8 -*- | ||
512 | 2 | ############################################################################## | ||
513 | 3 | # | ||
514 | 4 | # Copyright (C) 2013 Therp BV (<http://therp.nl>). | ||
515 | 5 | # All Rights Reserved | ||
516 | 6 | # | ||
517 | 7 | # This program is free software: you can redistribute it and/or modify | ||
518 | 8 | # it under the terms of the GNU General Public License as published by | ||
519 | 9 | # the Free Software Foundation, either version 3 of the License, or | ||
520 | 10 | # (at your option) any later version. | ||
521 | 11 | # | ||
522 | 12 | # This program is distributed in the hope that it will be useful, | ||
523 | 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
524 | 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
525 | 15 | # GNU General Public License for more details. | ||
526 | 16 | # | ||
527 | 17 | # You should have received a copy of the GNU General Public License | ||
528 | 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
529 | 19 | # | ||
530 | 20 | ############################################################################## | ||
531 | 21 | |||
532 | 22 | from openerp.osv import orm, fields | ||
533 | 23 | from openerp.tools.translate import _ | ||
534 | 24 | from openerp.addons.account_banking.wizard import banktools | ||
535 | 25 | |||
536 | 26 | class link_partner(orm.TransientModel): | ||
537 | 27 | _name = 'banking.link_partner' | ||
538 | 28 | _inherit = 'res.partner.address' | ||
539 | 29 | _description = 'Link partner' | ||
540 | 30 | |||
541 | 31 | _columns = { | ||
542 | 32 | 'name': fields.char( | ||
543 | 33 | 'Create partner with name', size=128, required=True), | ||
544 | 34 | 'supplier': fields.boolean('Supplier'), | ||
545 | 35 | 'customer': fields.boolean('Customer'), | ||
546 | 36 | 'partner_id': fields.many2one( | ||
547 | 37 | 'res.partner', 'or link existing partner'), | ||
548 | 38 | 'statement_line_id': fields.many2one( | ||
549 | 39 | 'account.bank.statement.line', | ||
550 | 40 | 'Statement line', required=True), | ||
551 | 41 | 'remote_account': fields.char( | ||
552 | 42 | 'Account number', size=24, readonly=True), | ||
553 | 43 | } | ||
554 | 44 | |||
555 | 45 | def create(self, cr, uid, vals, context=None): | ||
556 | 46 | """ | ||
557 | 47 | Get default values from the transaction data | ||
558 | 48 | on the statement line | ||
559 | 49 | """ | ||
560 | 50 | if vals and vals.get('statement_line_id'): | ||
561 | 51 | statement_line_obj = self.pool.get('account.bank.statement.line') | ||
562 | 52 | statement_line = statement_line_obj.browse( | ||
563 | 53 | cr, uid, vals['statement_line_id'], context=context) | ||
564 | 54 | transaction = statement_line.import_transaction_id | ||
565 | 55 | |||
566 | 56 | if statement_line.partner_bank_id: | ||
567 | 57 | raise orm.except_orm( | ||
568 | 58 | _('Error'), | ||
569 | 59 | _('Statement line is already linked to a bank account ')) | ||
570 | 60 | |||
571 | 61 | if not(transaction and transaction.remote_owner | ||
572 | 62 | and transaction.remote_account): | ||
573 | 63 | raise orm.except_orm( | ||
574 | 64 | _('Error'), | ||
575 | 65 | _('No transaction data on statement line')) | ||
576 | 66 | |||
577 | 67 | if 'supplier' not in vals and statement_line.amount < 0: | ||
578 | 68 | vals['supplier'] = True | ||
579 | 69 | if 'customer' not in vals and statement_line.amount > 0: | ||
580 | 70 | vals['customer'] = True | ||
581 | 71 | |||
582 | 72 | if not vals.get('street'): | ||
583 | 73 | vals['street'] = transaction.remote_owner_address | ||
584 | 74 | if not vals.get('street'): | ||
585 | 75 | vals['city'] = transaction.remote_owner_city | ||
586 | 76 | if not vals.get('country_id'): | ||
587 | 77 | vals['country_id'] = banktools.get_country_id( | ||
588 | 78 | self.pool, cr, uid, transaction, context=context) | ||
589 | 79 | if not vals.get('name'): | ||
590 | 80 | vals['name'] = transaction.remote_owner | ||
591 | 81 | if not vals.get('remote_account'): | ||
592 | 82 | vals['remote_account'] = transaction.remote_account | ||
593 | 83 | |||
594 | 84 | return super(link_partner, self).create( | ||
595 | 85 | cr, uid, vals, context=context) | ||
596 | 86 | |||
597 | 87 | def link_partner(self, cr, uid, ids, context=None): | ||
598 | 88 | statement_line_obj = self.pool.get( | ||
599 | 89 | 'account.bank.statement.line') | ||
600 | 90 | wiz = self.browse(cr, uid, ids[0], context=context) | ||
601 | 91 | |||
602 | 92 | if wiz.partner_id: | ||
603 | 93 | partner_id = wiz.partner_id.id | ||
604 | 94 | else: | ||
605 | 95 | partner_id = self.pool.get('res.partner').create( | ||
606 | 96 | cr, uid, { | ||
607 | 97 | 'name': wiz.name, | ||
608 | 98 | 'customer': wiz.customer, | ||
609 | 99 | 'supplier': wiz.supplier, | ||
610 | 100 | }, context=context) | ||
611 | 101 | wiz_read = self.read( | ||
612 | 102 | cr, uid, ids[0], context=context, load='_classic_write') | ||
613 | 103 | address_fields = self.pool.get( | ||
614 | 104 | 'res.partner.address')._columns.keys() | ||
615 | 105 | address_vals = {} | ||
616 | 106 | for field in self._columns.keys(): | ||
617 | 107 | # NB: wizard model contains 'partner_id' like the address | ||
618 | 108 | # but in this code path it is False | ||
619 | 109 | if field in address_fields: | ||
620 | 110 | address_vals[field] = wiz_read[field] | ||
621 | 111 | address_vals.update({ | ||
622 | 112 | 'partner_id': partner_id, | ||
623 | 113 | 'type': 'default', | ||
624 | 114 | }) | ||
625 | 115 | self.pool.get('res.partner.address').create( | ||
626 | 116 | cr, uid, address_vals, context=context) | ||
627 | 117 | |||
628 | 118 | partner_bank_id = banktools.create_bank_account( | ||
629 | 119 | self.pool, cr, uid, partner_id, | ||
630 | 120 | wiz.remote_account, wiz.name, | ||
631 | 121 | wiz.street, wiz.city, | ||
632 | 122 | wiz.country_id and wiz.country_id.id or False, | ||
633 | 123 | bic=wiz.statement_line_id.import_transaction_id.remote_bank_bic | ||
634 | 124 | ) | ||
635 | 125 | |||
636 | 126 | statement_line_ids = statement_line_obj.search( | ||
637 | 127 | cr, uid, | ||
638 | 128 | [('import_transaction_id.remote_account', '=', wiz.remote_account), | ||
639 | 129 | ('partner_bank_id', '=', False), | ||
640 | 130 | ('state', '=', 'draft')], context=context) | ||
641 | 131 | statement_line_obj.write( | ||
642 | 132 | cr, uid, statement_line_ids, | ||
643 | 133 | {'partner_bank_id': partner_bank_id, | ||
644 | 134 | 'partner_id': partner_id}, context=context) | ||
645 | 135 | |||
646 | 136 | return {'type': 'ir.actions.act_window_close'} | ||
647 | 137 | |||
648 | 138 | def create_act_window(self, cr, uid, ids, nodestroy=True, context=None): | ||
649 | 139 | """ | ||
650 | 140 | Return a popup window for this model | ||
651 | 141 | """ | ||
652 | 142 | if isinstance(ids, (int, long)): | ||
653 | 143 | ids = [ids] | ||
654 | 144 | return { | ||
655 | 145 | 'name': self._description, | ||
656 | 146 | 'view_type': 'form', | ||
657 | 147 | 'view_mode': 'form', | ||
658 | 148 | 'res_model': self._name, | ||
659 | 149 | 'domain': [], | ||
660 | 150 | 'context': context, | ||
661 | 151 | 'type': 'ir.actions.act_window', | ||
662 | 152 | 'target': 'new', | ||
663 | 153 | 'res_id': ids[0], | ||
664 | 154 | 'nodestroy': nodestroy, | ||
665 | 155 | } | ||
666 | 156 | |||
667 | 157 | |||
668 | 0 | 158 | ||
669 | === added file 'account_banking/wizard/link_partner.xml' | |||
670 | --- account_banking/wizard/link_partner.xml 1970-01-01 00:00:00 +0000 | |||
671 | +++ account_banking/wizard/link_partner.xml 2013-04-29 08:25:30 +0000 | |||
672 | @@ -0,0 +1,47 @@ | |||
673 | 1 | <?xml version="1.0" encoding="utf-8"?> | ||
674 | 2 | <openerp> | ||
675 | 3 | <data> | ||
676 | 4 | <record model="ir.ui.view" id="link_partner_view"> | ||
677 | 5 | <field name="name">Link partner wizard view</field> | ||
678 | 6 | <field name="type">form</field> | ||
679 | 7 | <field name="model">banking.link_partner</field> | ||
680 | 8 | <field name="arch" type="xml"> | ||
681 | 9 | <form string="Link partner"> | ||
682 | 10 | <group colspan="4" col="6"> | ||
683 | 11 | <field name="name" | ||
684 | 12 | attrs="{'readonly': [('partner_id', '!=', False)]}" /> | ||
685 | 13 | <field name="partner_id"/> | ||
686 | 14 | <field name="remote_account" /> | ||
687 | 15 | </group> | ||
688 | 16 | <group colspan="4" | ||
689 | 17 | string="Address" | ||
690 | 18 | attrs="{'invisible': [('partner_id', '!=', False)]}"> | ||
691 | 19 | <group colspan="2" col="2"> | ||
692 | 20 | <field name="street"/> | ||
693 | 21 | <field name="street2"/> | ||
694 | 22 | <field name="zip"/> | ||
695 | 23 | <field name="city"/> | ||
696 | 24 | <field name="country_id"/> | ||
697 | 25 | <field name="state_id"/> | ||
698 | 26 | </group> | ||
699 | 27 | <group colspan="2" col="2"> | ||
700 | 28 | <field name="phone"/> | ||
701 | 29 | <field name="fax"/> | ||
702 | 30 | <field name="mobile"/> | ||
703 | 31 | <field name="email" widget="email"/> | ||
704 | 32 | </group> | ||
705 | 33 | </group> | ||
706 | 34 | <button icon="gtk-cancel" string="Cancel" special="cancel" /> | ||
707 | 35 | <button icon="gtk-ok" string="Create partner" | ||
708 | 36 | name="link_partner" type="object" | ||
709 | 37 | attrs="{'invisible': [('partner_id', '!=', False)]}" | ||
710 | 38 | /> | ||
711 | 39 | <button icon="gtk-ok" string="Link existing partner" | ||
712 | 40 | name="link_partner" type="object" | ||
713 | 41 | attrs="{'invisible': [('partner_id', '==', False)]}" | ||
714 | 42 | /> | ||
715 | 43 | </form> | ||
716 | 44 | </field> | ||
717 | 45 | </record> | ||
718 | 46 | </data> | ||
719 | 47 | </openerp> |
l.183 I think the intended tuple of types was (int, long) instead of (int, float).
l.182 an indentation level could be avoided by returning early in the method (maybe a matter of taste though)
Besides that, LGTM