Merge lp:~akretion-team/banking-addons/bank-statement-reconcile-61-ref-base-import into lp:banking-addons/bank-statement-reconcile-61
- bank-statement-reconcile-61-ref-base-import
- Merge into bank-statement-reconcile-61
Status: | Merged |
---|---|
Merged at revision: | 81 |
Proposed branch: | lp:~akretion-team/banking-addons/bank-statement-reconcile-61-ref-base-import |
Merge into: | lp:banking-addons/bank-statement-reconcile-61 |
Diff against target: |
507 lines (+94/-74) 5 files modified
account_statement_base_import/parser/file_parser.py (+9/-8) account_statement_base_import/parser/parser.py (+30/-26) account_statement_base_import/statement.py (+47/-31) account_statement_base_import/statement_view.xml (+1/-2) account_statement_base_import/wizard/import_statement.py (+7/-7) |
To merge this branch: | bzr merge lp:~akretion-team/banking-addons/bank-statement-reconcile-61-ref-base-import |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Guewen Baconnier @ Camptocamp | code review, no test | Approve | |
Holger Brunn (Therp) | code review, no test | Approve | |
Review via email: mp+159104@code.launchpad.net |
Commit message
Description of the change
In this merge proposal, I submit some changes in the module account_
- Fix argument keys_to_validate in the init of the file_parser
- add the possibility to force the dialect for the csv dictreader
- fix the field : import_type of the class account_
- remove sapce at the end of lines due to my IDE
- fix typo in the name of the method :prepare_
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
Holger Brunn (Therp) (hbrunn) wrote : | # |
as of line 406: you can indeed remove the unlink, as the transaction is rolled back anyway
- 79. By Benoit Guillot - http://www.akretion.com
-
[IMP] fix keys_to_validate, remove useless unlink, fix dialect
Benoit Guillot - http://www.akretion.com (benoit-guillot-z) wrote : | # |
I change with the several comments
Holger Brunn (Therp) (hbrunn) : | # |
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
LGTM
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : | # |
Thanks Benoit.
I merged your proposal.
Did you created the MP for the version 7 somewhere?
Benoit Guillot - http://www.akretion.com (benoit-guillot-z) wrote : | # |
Thanks Guewen for the merge !
I haven't created the MP for the v7.0 yet. Sebastien wants to make another MP on the v6.1, after that I will make the MP for the v7.0.
Preview Diff
1 | === modified file 'account_statement_base_import/parser/file_parser.py' |
2 | --- account_statement_base_import/parser/file_parser.py 2012-11-26 10:23:58 +0000 |
3 | +++ account_statement_base_import/parser/file_parser.py 2013-05-31 13:57:28 +0000 |
4 | @@ -32,13 +32,13 @@ |
5 | """ |
6 | Generic abstract class for defining parser for .csv or .xls file format. |
7 | """ |
8 | - |
9 | - def __init__(self, parse_name, keys_to_validate=[], ftype='csv', convertion_dict=None, header=None, *args, **kwargs): |
10 | + |
11 | + def __init__(self, parse_name, keys_to_validate=None, ftype='csv', convertion_dict=None, header=None, dialect=None, *args, **kwargs): |
12 | """ |
13 | :param char: parse_name : The name of the parser |
14 | :param list: keys_to_validate : contain the key that need to be present in the file |
15 | :param char ftype: extension of the file (could be csv or xls) |
16 | - :param: convertion_dict : keys and type to convert of every column in the file like |
17 | + :param: convertion_dict : keys and type to convert of every column in the file like |
18 | { |
19 | 'ref': unicode, |
20 | 'label': unicode, |
21 | @@ -48,18 +48,19 @@ |
22 | } |
23 | :param list: header : specify header fields if the csv file has no header |
24 | """ |
25 | - |
26 | + |
27 | super(FileParser, self).__init__(parse_name, *args, **kwargs) |
28 | if ftype in ('csv', 'xls'): |
29 | self.ftype = ftype |
30 | else: |
31 | raise Exception(_('Invalide file type %s. please use csv or xls') % (ftype)) |
32 | - self.keys_to_validate = keys_to_validate |
33 | + self.keys_to_validate = keys_to_validate or [] |
34 | self.convertion_dict = convertion_dict |
35 | self.fieldnames = header |
36 | self._datemode = 0 # used only for xls documents, |
37 | # 0 means Windows mode (1900 based dates). |
38 | # Set in _parse_xls, from the contents of the file |
39 | + self.dialect = dialect |
40 | |
41 | def _custom_format(self, *args, **kwargs): |
42 | """ |
43 | @@ -78,7 +79,7 @@ |
44 | Launch the parsing through .csv or .xls depending on the |
45 | given ftype |
46 | """ |
47 | - |
48 | + |
49 | res = None |
50 | if self.ftype == 'csv': |
51 | res = self._parse_csv() |
52 | @@ -116,8 +117,8 @@ |
53 | csv_file = tempfile.NamedTemporaryFile() |
54 | csv_file.write(self.filebuffer) |
55 | csv_file.flush() |
56 | - with open(csv_file.name, 'rU') as fobj: |
57 | - reader = UnicodeDictReader(fobj, fieldnames=self.fieldnames) |
58 | + with open(csv_file.name, 'rU') as fobj: |
59 | + reader = UnicodeDictReader(fobj, fieldnames=self.fieldnames, dialect=self.dialect) |
60 | return list(reader) |
61 | |
62 | def _parse_xls(self): |
63 | |
64 | === modified file 'account_statement_base_import/parser/parser.py' |
65 | --- account_statement_base_import/parser/parser.py 2012-11-23 16:27:24 +0000 |
66 | +++ account_statement_base_import/parser/parser.py 2013-05-31 13:57:28 +0000 |
67 | @@ -26,10 +26,15 @@ |
68 | pos = utf8_data.tell() |
69 | sample_data = utf8_data.read(1024) |
70 | utf8_data.seek(pos) |
71 | - dialect = sniffer.sniff(sample_data, delimiters=',;\t') |
72 | + if not kwargs.get('dialect'): |
73 | + dialect = sniffer.sniff(sample_data, delimiters=',;\t') |
74 | + if 'dialect' in kwargs: |
75 | + del kwargs['dialect'] |
76 | + else: |
77 | + dialect = kwargs.pop('dialect') |
78 | csv_reader = csv.DictReader(utf8_data, dialect=dialect, **kwargs) |
79 | for row in csv_reader: |
80 | - yield dict([(key, unicode(value, 'utf-8')) for key, value in row.iteritems()]) |
81 | + yield dict([(unicode(key, 'utf-8'), unicode(value, 'utf-8')) for key, value in row.iteritems()]) |
82 | |
83 | class BankStatementImportParser(object): |
84 | """ |
85 | @@ -38,7 +43,7 @@ |
86 | own. If your file is a .csv or .xls format, you should consider inheirt |
87 | from the FileParser instead. |
88 | """ |
89 | - |
90 | + |
91 | def __init__(self, parser_name, *args, **kwargs): |
92 | # The name of the parser as it will be called |
93 | self.parser_name = parser_name |
94 | @@ -50,7 +55,7 @@ |
95 | # Concatenate here the global commission taken by the bank/office |
96 | # for this statement. |
97 | self.commission_global_amount = None |
98 | - |
99 | + |
100 | @classmethod |
101 | def parser_for(cls, parser_name): |
102 | """ |
103 | @@ -58,17 +63,17 @@ |
104 | return the good class from his name. |
105 | """ |
106 | return False |
107 | - |
108 | + |
109 | def _decode_64b_stream(self): |
110 | """ |
111 | Decode self.filebuffer in base 64 and override it |
112 | """ |
113 | self.filebuffer = base64.b64decode(self.filebuffer) |
114 | return True |
115 | - |
116 | + |
117 | def _format(self, decode_base_64=True, **kwargs): |
118 | """ |
119 | - Decode into base 64 if asked and Format the given filebuffer by calling |
120 | + Decode into base 64 if asked and Format the given filebuffer by calling |
121 | _custom_format method. |
122 | """ |
123 | if decode_base_64: |
124 | @@ -83,43 +88,43 @@ |
125 | """ |
126 | return NotImplementedError |
127 | |
128 | - |
129 | + |
130 | def _pre(self, *args, **kwargs): |
131 | """ |
132 | - Implement a method in your parser to make a pre-treatment on datas before parsing |
133 | + Implement a method in your parser to make a pre-treatment on datas before parsing |
134 | them, like concatenate stuff, and so... Work on self.filebuffer |
135 | """ |
136 | return NotImplementedError |
137 | |
138 | def _parse(self, *args, **kwargs): |
139 | """ |
140 | - Implement a method in your parser to save the result of parsing self.filebuffer |
141 | + Implement a method in your parser to save the result of parsing self.filebuffer |
142 | in self.result_row_list instance property. |
143 | """ |
144 | return NotImplementedError |
145 | - |
146 | + |
147 | def _validate(self, *args, **kwargs): |
148 | """ |
149 | Implement a method in your parser to validate the self.result_row_list instance |
150 | property and raise an error if not valid. |
151 | """ |
152 | return NotImplementedError |
153 | - |
154 | + |
155 | def _post(self, *args, **kwargs): |
156 | """ |
157 | Implement a method in your parser to make some last changes on the result of parsing |
158 | - the datas, like converting dates, computing commission, ... |
159 | + the datas, like converting dates, computing commission, ... |
160 | Work on self.result_row_list and put the commission global amount if any |
161 | in the self.commission_global_amount one. |
162 | """ |
163 | return NotImplementedError |
164 | - |
165 | - |
166 | - |
167 | + |
168 | + |
169 | + |
170 | def get_st_line_vals(self, line, *args, **kwargs): |
171 | """ |
172 | - Implement a method in your parser that must return a dict of vals that can be |
173 | - passed to create method of statement line in order to record it. It is the responsibility |
174 | + Implement a method in your parser that must return a dict of vals that can be |
175 | + passed to create method of statement line in order to record it. It is the responsibility |
176 | of every parser to give this dict of vals, so each one can implement his |
177 | own way of recording the lines. |
178 | :param: line: a dict of vals that represent a line of result_row_list |
179 | @@ -133,17 +138,17 @@ |
180 | } |
181 | """ |
182 | return NotImplementedError |
183 | - |
184 | + |
185 | def get_st_line_commision(self, *args, **kwargs): |
186 | """ |
187 | This is called by the importation method to create the commission line in |
188 | the bank statement. We will always create one line for the commission in the |
189 | - bank statement, but it could be computated from a value of each line, or given |
190 | + bank statement, but it could be computated from a value of each line, or given |
191 | in a single line for the whole file. |
192 | return: float of the whole commission (self.commission_global_amount) |
193 | """ |
194 | return self.commission_global_amount |
195 | - |
196 | + |
197 | def parse(self, filebuffer, *args, **kwargs): |
198 | """ |
199 | This will be the method that will be called by wizard, button and so |
200 | @@ -151,7 +156,7 @@ |
201 | that need to be define for each parser. |
202 | Return: |
203 | [] of rows as {'key':value} |
204 | - |
205 | + |
206 | Note: The row_list must contain only value that are present in the account. |
207 | bank.statement.line object !!! |
208 | """ |
209 | @@ -165,7 +170,7 @@ |
210 | self._validate(*args, **kwargs) |
211 | self._post(*args, **kwargs) |
212 | return self.result_row_list |
213 | - |
214 | + |
215 | def itersubclasses(cls, _seen=None): |
216 | """ |
217 | itersubclasses(cls) |
218 | @@ -179,7 +184,7 @@ |
219 | >>> class C(A): pass |
220 | >>> class D(B,C): pass |
221 | >>> class E(D): pass |
222 | - >>> |
223 | + >>> |
224 | >>> for cls in itersubclasses(A): |
225 | ... print(cls.__name__) |
226 | B |
227 | @@ -204,7 +209,7 @@ |
228 | yield sub |
229 | for sub in itersubclasses(sub, _seen): |
230 | yield sub |
231 | - |
232 | + |
233 | def new_bank_statement_parser(parser_name, *args, **kwargs): |
234 | """ |
235 | Return an instance of the good parser class base on the providen name |
236 | @@ -215,4 +220,3 @@ |
237 | if cls.parser_for(parser_name): |
238 | return cls(parser_name, *args, **kwargs) |
239 | raise ValueError |
240 | - |
241 | |
242 | === modified file 'account_statement_base_import/statement.py' |
243 | --- account_statement_base_import/statement.py 2012-09-25 08:05:34 +0000 |
244 | +++ account_statement_base_import/statement.py 2013-05-31 13:57:28 +0000 |
245 | @@ -29,34 +29,42 @@ |
246 | from parser import new_bank_statement_parser |
247 | import sys |
248 | import traceback |
249 | +import logging |
250 | +_logger = logging.getLogger(__name__) |
251 | + |
252 | |
253 | class AccountStatementProfil(Model): |
254 | _inherit = "account.statement.profile" |
255 | - |
256 | - |
257 | + |
258 | + |
259 | def get_import_type_selection(self, cr, uid, context=None): |
260 | """ |
261 | Has to be inherited to add parser |
262 | """ |
263 | return [('generic_csvxls_so', 'Generic .csv/.xls based on SO Name')] |
264 | - |
265 | - |
266 | + |
267 | + def _get_import_type_selection(self, cr, uid, context=None): |
268 | + """ |
269 | + Has to be inherited to add parser |
270 | + """ |
271 | + return self.get_import_type_selection(cr, uid, context=context) |
272 | + |
273 | _columns = { |
274 | - 'launch_import_completion': fields.boolean("Launch completion after import", |
275 | + 'launch_import_completion': fields.boolean("Launch completion after import", |
276 | help="Tic that box to automatically launch the completion on each imported\ |
277 | file using this profile."), |
278 | 'last_import_date': fields.datetime("Last Import Date"), |
279 | 'rec_log': fields.text('log', readonly=True), |
280 | - 'import_type': fields.selection(get_import_type_selection, 'Type of import', required=True, |
281 | + 'import_type': fields.selection(_get_import_type_selection, 'Type of import', required=True, |
282 | help = "Choose here the method by which you want to import bank statement for this profile."), |
283 | - |
284 | + |
285 | } |
286 | - |
287 | + |
288 | def write_logs_after_import(self, cr, uid, ids, statement_id, num_lines, context): |
289 | """ |
290 | - Write the log in the logger + in the log field of the profile to report the user about |
291 | + Write the log in the logger + in the log field of the profile to report the user about |
292 | what has been done. |
293 | - |
294 | + |
295 | :param int/long statement_id: ID of the concerned account.bank.statement |
296 | :param int/long num_lines: Number of line that have been parsed |
297 | :return: True |
298 | @@ -71,11 +79,11 @@ |
299 | + _("Bank Statement ID %s have been imported with %s lines ") %(statement_id, num_lines)] |
300 | log = "\n".join(log_line) |
301 | self.write(cr, uid, id, {'rec_log' : log, 'last_import_date':import_date}, context=context) |
302 | - logger.notifyChannel('Bank Statement Import', netsvc.LOG_INFO, |
303 | + logger.notifyChannel('Bank Statement Import', netsvc.LOG_INFO, |
304 | "Bank Statement ID %s have been imported with %s lines "%(statement_id, num_lines)) |
305 | return True |
306 | - |
307 | - def prepare_global_commission_line_vals(self, cr, uid, parser, |
308 | + |
309 | + def prepare_global_commission_line_vals(self, cr, uid, parser, |
310 | result_row_list, profile, statement_id, context): |
311 | """ |
312 | Prepare the global commission line if there is one. The global |
313 | @@ -110,15 +118,25 @@ |
314 | 'already_completed': True, |
315 | } |
316 | return comm_values |
317 | - |
318 | - def prepare_statetement_lines_vals(self, cursor, uid, parser_vals, |
319 | + |
320 | + def prepare_statetement_lines_vals(self, cursor, uid, parser_vals, |
321 | + account_payable, account_receivable, statement_id, context): |
322 | + """ |
323 | + Method to ensure backward compatibility with the old name of the method. |
324 | + """ |
325 | + _logger.warning(_("The method prepare_statetement_lines_vals shouldn't " |
326 | + "be used anymore, use : prepare_statement_lines_vals")) |
327 | + return self.prepare_statement_lines_vals(cursor, uid, parser_vals, |
328 | + account_payable, account_receivable, statement_id, context) |
329 | + |
330 | + def prepare_statement_lines_vals(self, cursor, uid, parser_vals, |
331 | account_payable, account_receivable, statement_id, context): |
332 | """ |
333 | Hook to build the values of a line from the parser returned values. At |
334 | least it fullfill the statement_id and account_id. Overide it to add your |
335 | - own completion if needed. |
336 | - |
337 | - :param dict of vals from parser for account.bank.statement.line (called by |
338 | + own completion if needed. |
339 | + |
340 | + :param dict of vals from parser for account.bank.statement.line (called by |
341 | parser.get_st_line_vals) |
342 | :param int/long account_payable: ID of the receivable account to use |
343 | :param int/long account_receivable: ID of the payable account to use |
344 | @@ -136,7 +154,7 @@ |
345 | account_payable |
346 | ) |
347 | return values |
348 | - |
349 | + |
350 | def statement_import(self, cursor, uid, ids, profile_id, file_stream, ftype="csv", context=None): |
351 | """ |
352 | Create a bank statement with the given profile and parser. It will fullfill the bank statement |
353 | @@ -144,7 +162,7 @@ |
354 | the right account). This will be done in a second step with the completion rules. |
355 | It will also create the commission line if it apply and record the providen file as |
356 | an attachement of the bank statement. |
357 | - |
358 | + |
359 | :param int/long profile_id: ID of the profile used to import the file |
360 | :param filebuffer file_stream: binary of the providen file |
361 | :param char: ftype represent the file exstension (csv by default) |
362 | @@ -160,7 +178,7 @@ |
363 | _("No Profile !"), |
364 | _("You must provide a valid profile to import a bank statement !")) |
365 | prof = prof_obj.browse(cursor,uid,profile_id,context) |
366 | - |
367 | + |
368 | parser = new_bank_statement_parser(prof.import_type, ftype=ftype) |
369 | result_row_list = parser.parse(file_stream) |
370 | # Check all key are present in account.bank.statement.line !! |
371 | @@ -170,15 +188,15 @@ |
372 | raise osv.except_osv( |
373 | _("Missing column !"), |
374 | _("Column %s you try to import is not present in the bank statement line !") %(col)) |
375 | - |
376 | - statement_id = statement_obj.create(cursor,uid,{'profile_id':prof.id,},context) |
377 | + |
378 | + statement_id = statement_obj.create(cursor,uid,{'profile_id':prof.id,},context) |
379 | account_receivable, account_payable = statement_obj.get_default_pay_receiv_accounts(cursor, uid, context) |
380 | try: |
381 | # Record every line in the bank statement and compute the global commission |
382 | # based on the commission_amount column |
383 | for line in result_row_list: |
384 | parser_vals = parser.get_st_line_vals(line) |
385 | - values = self.prepare_statetement_lines_vals(cursor, uid, parser_vals, account_payable, |
386 | + values = self.prepare_statement_lines_vals(cursor, uid, parser_vals, account_payable, |
387 | account_receivable, statement_id, context) |
388 | # we finally create the line in system |
389 | statement_line_obj.create(cursor, uid, values, context=context) |
390 | @@ -186,7 +204,7 @@ |
391 | comm_vals = self.prepare_global_commission_line_vals(cursor, uid, parser, result_row_list, prof, statement_id, context) |
392 | if comm_vals: |
393 | res = statement_line_obj.create(cursor, uid, comm_vals,context=context) |
394 | - |
395 | + |
396 | attachment_obj.create( |
397 | cursor, |
398 | uid, |
399 | @@ -199,17 +217,16 @@ |
400 | 'res_id': statement_id, |
401 | }, |
402 | context=context |
403 | - ) |
404 | + ) |
405 | # If user ask to launch completion at end of import, do it ! |
406 | if prof.launch_import_completion: |
407 | statement_obj.button_auto_completion(cursor, uid, [statement_id], context) |
408 | - |
409 | + |
410 | # Write the needed log infos on profile |
411 | self.write_logs_after_import(cursor, uid, prof.id, statement_id, |
412 | len(result_row_list), context) |
413 | - |
414 | + |
415 | except Exception, exc: |
416 | - statement_obj.unlink(cursor, uid, [statement_id]) |
417 | error_type, error_value, trbk = sys.exc_info() |
418 | st = "Error: %s\nDescription: %s\nTraceback:" % (error_type.__name__, error_value) |
419 | st += ''.join(traceback.format_tb(trbk, 30)) |
420 | @@ -217,7 +234,6 @@ |
421 | _("Statement import error"), |
422 | _("The statement cannot be created : %s") %(st)) |
423 | return statement_id |
424 | - |
425 | |
426 | |
427 | class AccountStatementLine(Model): |
428 | @@ -229,7 +245,7 @@ |
429 | _inherit = "account.bank.statement.line" |
430 | |
431 | _columns={ |
432 | - 'commission_amount': fields.sparse(type='float', string='Line Commission Amount', |
433 | + 'commission_amount': fields.sparse(type='float', string='Line Commission Amount', |
434 | serialization_field='additionnal_bank_fields'), |
435 | |
436 | } |
437 | |
438 | === modified file 'account_statement_base_import/statement_view.xml' |
439 | --- account_statement_base_import/statement_view.xml 2012-08-02 12:46:12 +0000 |
440 | +++ account_statement_base_import/statement_view.xml 2013-05-31 13:57:28 +0000 |
441 | @@ -16,7 +16,7 @@ |
442 | <field name="import_type"/> |
443 | <button name="%(account_statement_base_import.statement_importer_action)d" |
444 | string="Import Bank Statement" |
445 | - type="action" icon="gtk-ok" |
446 | + type="action" icon="gtk-ok" |
447 | colspan = "2"/> |
448 | <separator colspan="4" string="Import Logs"/> |
449 | <field name="rec_log" colspan="4" nolabel="1"/> |
450 | @@ -39,6 +39,5 @@ |
451 | </field> |
452 | </record> |
453 | |
454 | - |
455 | </data> |
456 | </openerp> |
457 | |
458 | === modified file 'account_statement_base_import/wizard/import_statement.py' |
459 | --- account_statement_base_import/wizard/import_statement.py 2012-11-27 10:51:47 +0000 |
460 | +++ account_statement_base_import/wizard/import_statement.py 2013-05-31 13:57:28 +0000 |
461 | @@ -29,7 +29,7 @@ |
462 | |
463 | class CreditPartnerStatementImporter(osv.osv_memory): |
464 | _name = "credit.statement.import" |
465 | - |
466 | + |
467 | def default_get(self, cr, uid, fields, context=None): |
468 | if context is None: context = {} |
469 | res = {} |
470 | @@ -41,7 +41,7 @@ |
471 | other_vals = self.onchange_profile_id(cr, uid, [], res['profile_id'], context=context) |
472 | res.update(other_vals.get('value',{})) |
473 | return res |
474 | - |
475 | + |
476 | _columns = { |
477 | 'profile_id': fields.many2one('account.statement.profile', |
478 | 'Import configuration parameter', |
479 | @@ -63,23 +63,23 @@ |
480 | ), |
481 | 'receivable_account_id': fields.many2one('account.account', |
482 | 'Force Receivable/Payable Account'), |
483 | - 'force_partner_on_bank': fields.boolean('Force partner on bank move', |
484 | + 'force_partner_on_bank': fields.boolean('Force partner on bank move', |
485 | help="Tic that box if you want to use the credit insitute partner\ |
486 | in the counterpart of the treasury/banking move." |
487 | ), |
488 | - 'balance_check': fields.boolean('Balance check', |
489 | + 'balance_check': fields.boolean('Balance check', |
490 | help="Tic that box if you want OpenERP to control the start/end balance\ |
491 | before confirming a bank statement. If don't ticked, no balance control will be done." |
492 | ), |
493 | - } |
494 | - |
495 | + } |
496 | + |
497 | def onchange_profile_id(self, cr, uid, ids, profile_id, context=None): |
498 | res={} |
499 | if profile_id: |
500 | c = self.pool.get("account.statement.profile").browse(cr,uid,profile_id) |
501 | res = {'value': {'partner_id': c.partner_id and c.partner_id.id or False, |
502 | 'journal_id': c.journal_id and c.journal_id.id or False, 'commission_account_id': \ |
503 | - c.commission_account_id and c.commission_account_id.id or False, |
504 | + c.commission_account_id and c.commission_account_id.id or False, |
505 | 'receivable_account_id': c.receivable_account_id and c.receivable_account_id.id or False, |
506 | 'commission_a':c.commission_analytic_id and c.commission_analytic_id.id or False, |
507 | 'force_partner_on_bank':c.force_partner_on_bank, |
"remove sapce at the end of lines due to my IDE"
Can you remove this option from your IDE please?
You removed the mutable in (l.11) the keyword argument, which is correct. But I don't think the change of the line 52 is fine. I would prefer to initialize `self.keys_ to_validate` to an empty list when the argument is None. Thus, the change is backward compatible and you don't need to verify the attribute everywhere it could be used.
l.78: the del on the kwargs could fail with a KeyError
l.318: fixing the typo errors in method names is fine, but I think you should ensure backward compatibility at least for public methods, keeping the old method which delegate the call to the new one (ideally with a warning).
Thanks for your MP