Merge lp:~akretion-team/openobject-addons/5.2-refactor-methods-splits into lp:openobject-addons
- 5.2-refactor-methods-splits
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 3054 |
Proposed branch: | lp:~akretion-team/openobject-addons/5.2-refactor-methods-splits |
Merge into: | lp:openobject-addons |
Diff against target: |
169 lines (+80/-56) 1 file modified
account/invoice.py (+80/-56) |
To merge this branch: | bzr merge lp:~akretion-team/openobject-addons/5.2-refactor-methods-splits |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Raphaël Valyi - http://www.akretion.com (community) | Needs Resubmitting | ||
Xavier (Open ERP) (community) | technical | Needs Information | |
Review via email: mp+19842@code.launchpad.net |
Commit message
Description of the change
Raphaël Valyi - http://www.akretion.com (rvalyi) wrote : | # |
Xavier (Open ERP) (xmo-deactivatedaccount) wrote : | # |
A few questions/
* In `compute_
* I see that you added nice docstrings for the extracted `group_lines` and `inv_line_
* On `group_lines`'s docstring, why groups "eventually"? From what I read, it seems to merge lines by hashcode (by the way, "merge" might be a better name than "group" given the semantic differences with `itertools.
* Finally, `inv_line_
Raphaël Valyi - http://www.akretion.com (rvalyi) wrote : | # |
> A few questions/
>
> * In `compute_
> then return it unmodified, is there a reason? Is this a hook for later
> alterations?
-> Well, as you can see, in compute_
>
> * I see that you added nice docstrings for the extracted `group_lines` and
> `inv_line_
> add some to `check_tax_lines` and `compute_
> document the arguments a bit? (the method names read clear enough, though they
> might be lying, but the arguments aren't as clear). Not the cr & uid stuff as
> they're "standard", but the rest?
-> I don't claim to understand or be willing to understand all legacy Tiny code here... I just pretend to here to apply basic software engineering principles where methods shouldn't be too fat to be easily over-ridable in a fine grained manner (just like overriders should call super and a few basic OOP rules like that). Yes, for those methods in particular, method names are somewhat clear and that's probably better that the nodoc situation of before. I don't claim I master enough what is going on under the cover to make much smarter docstrings here, you better ask that to Fabien or something I'm afraid...
> * On `group_lines`'s docstring, why groups "eventually"? From what I read, it
> seems to merge lines by hashcode (by the way, "merge" might be a better name
> than "group" given the semantic differences with `itertools.
> also rename `tmp` to `key`.
-> Okay, let's go for that one...
>
> * Finally, `inv_line_
> replacing the current +-based concatenation with a simple string format, it
> would be more readable and would probably be just as fast if not faster.
-> be my guest to improve things further. My philosophy here has been to improve the existing code using basic/automatic code extraction methods without changing the logic in order to avoid confusing Tiny and taking the risk you refuse that clear improvement over that existing crappy piece of code.
Admit that in the past, the most complex a merge proposal was, the more unlikely it was to get merged, no matter how good it was, just because Tiny wouldn't give a shit about third party work. Now, we are okay to adapt to a more open Tiny, but please admit it takes some time because we wait for clear effective signals from Tiny before we are willing to spend and risk to waste so much time again (and ERPScenario and OpenETL wastes aren't that far away, remember?)...
So my take is: merge that first, it's iso-functional and even backward compatible, then use your editor time to fight against Fabien and other Tiny's gods to try to improve the code logic, cause I can't afford spending more time myself to get such basic improvements merged in (con...
Xavier (Open ERP) (xmo-deactivatedaccount) wrote : | # |
> Well, as you can see, in compute_
Yeah, no problem with that, the part I find weird is the last line of the method:
return total, total_currency, invoice_move_lines
here, the method *returns* invoice_move_lines, and I don't see the reason for that as the caller already has all the invoice_move_lines it wants (unless `compute_
> I don't claim to understand or be willing to understand all legacy Tiny code here... I just pretend to here to apply basic software engineering principles where methods shouldn't be too fat to be easily over-ridable in a fine grained manner
OK.
Xavier (Open ERP) (xmo-deactivatedaccount) wrote : | # |
as for the next part:
> be my guest to improve things further. My philosophy here has been to improve the existing code using basic/automatic code extraction methods without changing the logic in order to avoid confusing Tiny and taking the risk you refuse that clear improvement over that existing crappy piece of code.
You could just have said that you believe this suggestion to be out of scope for your branch, it'd have been shorter and to the point.
> I hope it doesn't sound rude
Well I'm getting used to your rants so I don't really mind; I'm not sure everybody has as thick a skin as mine though so while I understand your frustration I believe sugar-coating your words a bit (and cutting down on your word count) would get your points across better. Generally speaking and considering the form of your replies there's a high risk people will respond to your tone, not your content, and I'm not sure that's for the best.
As for the merge semantics stuff, I'm not going to claim good enough knowledge of the functional side to comment.
Raphaël Valyi - http://www.akretion.com (rvalyi) wrote : | # |
> here, the method *returns* invoice_move_lines, and I don't see the reason for
> that as the caller already has all the invoice_move_lines it wants (unless
> `compute_
> reason whatsoever to).
Well, unless I'm dumb tonight, it's just what it does: the compute_
Now if you see better method name or code organization please go on. Again that wouldn't be the first place in the OpenERP codebase where could easily find better names (we could speak about the foreign key name conventions and their numerous exceptions for instance)...
[...]
> Generally speaking and considering the form of your replies there's a high risk people will respond > to your tone, not your content, and I'm not sure that's for the best.
The issue is: we have been very very patient for years with Tiny with a very keen tone and the result was a huge incapacity to integrate any third party work no matter the content, such as https:/
So the community is tired of words, it now judges by acts only and yet for some months I believe (and see partner exchanges or community meeting or experts lists if you think that was just me, some even left recently as I said).
At the same time we invest pretty heavily on our best ERP that is still OpenERP as you see. And while OpenERP as clearly been in the lead for the last 3 years, we are a bit afraid to see that Tiny is somewhat likely to let Tryton pass within 2 years because they would make the error to dream they are ready to scale with such a poor codebase quality (even if competitors were worse it doesn't mean it's enough to scale, far from it...). That doesn't excite us at the point we would lick Tiny's boots. At this stage, the more friendly stance we can have is rather try to trigger an electroshock in Tiny's megalomania (the +500 module, Saas ready, RAD slideware)...
So don't take it personally cause we appreciate a lot the great work you are throwing in, it has been a long time... But please don't expect either people can work like mad, propose a ton of improvements, get their work largely ignored and keep smiling full of faith while competitors make their way faster... At least we continue to work in Tiny's direction...
So do you still have question or see issues with that merge? I mean yeah, it's probably far from perfect but again I try to be pragmatic: my goal is not to re-make the world here but just modularize existing stuff decently. Then I can do that elsewhere and that would provide at least much better options to extension modules for 2010 than just copy/paste those 170 lines of code... I think it has more value I do similar simple changes elsewhere where it's very much required rather than invest it all upon that one and let the rest ( https:/...
Preview Diff
1 | === modified file 'account/invoice.py' |
2 | --- account/invoice.py 2010-02-16 14:27:23 +0000 |
3 | +++ account/invoice.py 2010-02-23 05:42:20 +0000 |
4 | @@ -630,8 +630,85 @@ |
5 | if res and res['value']: |
6 | self.write(cr, uid, [inv.id], res['value']) |
7 | return True |
8 | + |
9 | + def check_tax_lines(self, cr, uid, inv, compute_taxes, ait_obj): |
10 | + if not inv.tax_line: |
11 | + for tax in compute_taxes.values(): |
12 | + ait_obj.create(cr, uid, tax) |
13 | + else: |
14 | + tax_key = [] |
15 | + for tax in inv.tax_line: |
16 | + if tax.manual: |
17 | + continue |
18 | + key = (tax.tax_code_id.id, tax.base_code_id.id, tax.account_id.id) |
19 | + tax_key.append(key) |
20 | + if not key in compute_taxes: |
21 | + raise osv.except_osv(_('Warning !'), _('Global taxes defined, but are not in invoice lines !')) |
22 | + base = compute_taxes[key]['base'] |
23 | + if abs(base - tax.base) > inv.company_id.currency_id.rounding: |
24 | + raise osv.except_osv(_('Warning !'), _('Tax base different !\nClick on compute to update tax base')) |
25 | + for key in compute_taxes: |
26 | + if not key in tax_key: |
27 | + raise osv.except_osv(_('Warning !'), _('Taxes missing !')) |
28 | + |
29 | + def compute_invoice_totals(self, cr, uid, inv, company_currency, ref, invoice_move_lines): |
30 | + total = 0 |
31 | + total_currency = 0 |
32 | + for i in invoice_move_lines: |
33 | + if inv.currency_id.id != company_currency: |
34 | + i['currency_id'] = inv.currency_id.id |
35 | + i['amount_currency'] = i['price'] |
36 | + i['price'] = cur_obj.compute(cr, uid, inv.currency_id.id, |
37 | + company_currency, i['price'], |
38 | + context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}) |
39 | + else: |
40 | + i['amount_currency'] = False |
41 | + i['currency_id'] = False |
42 | + i['ref'] = ref |
43 | + if inv.type in ('out_invoice','in_refund'): |
44 | + total += i['price'] |
45 | + total_currency += i['amount_currency'] or i['price'] |
46 | + i['price'] = - i['price'] |
47 | + else: |
48 | + total -= i['price'] |
49 | + total_currency -= i['amount_currency'] or i['price'] |
50 | + return total, total_currency, invoice_move_lines |
51 | + |
52 | + def inv_line_characteristic_hashcode(self, invoice, invoice_line): |
53 | + """Overridable hashcode generation for invoice lines. Lines having the same hashcode |
54 | + will be grouped together if the journal has the 'group line' option. Of course a module |
55 | + can add fields to invoice lines that would need to be tested too before merging lines |
56 | + or not.""" |
57 | + code = str(invoice_line['account_id']) |
58 | + code += '-'+str(invoice_line.get('tax_code_id',"False")) |
59 | + code += '-'+str(invoice_line.get('product_id',"False")) |
60 | + code += '-'+str(invoice_line.get('analytic_account_id',"False")) |
61 | + code += '-'+str(invoice_line.get('date_maturity',"False")) |
62 | + return code |
63 | + |
64 | + def group_lines(self, cr, uid, iml, line, inv): |
65 | + """Merge account move lines (and hence analytic lines) if invoice line hashcodes are equals""" |
66 | + if inv.journal_id.group_invoice_lines: |
67 | + line2 = {} |
68 | + for x, y, l in line: |
69 | + tmp = self.inv_line_characteristic_hashcode(inv, l) |
70 | + |
71 | + if tmp in line2: |
72 | + am = line2[tmp]['debit'] - line2[tmp]['credit'] + (l['debit'] - l['credit']) |
73 | + line2[tmp]['debit'] = (am > 0) and am or 0.0 |
74 | + line2[tmp]['credit'] = (am < 0) and -am or 0.0 |
75 | + line2[tmp]['tax_amount'] += l['tax_amount'] |
76 | + line2[tmp]['analytic_lines'] += l['analytic_lines'] |
77 | + else: |
78 | + line2[tmp] = l |
79 | + line = [] |
80 | + for key, val in line2.items(): |
81 | + line.append((0,0,val)) |
82 | + |
83 | + return line |
84 | |
85 | def action_move_create(self, cr, uid, ids, *args): |
86 | + """Creates invoice related analytics and financial move lines""" |
87 | ait_obj = self.pool.get('account.invoice.tax') |
88 | cur_obj = self.pool.get('res.currency') |
89 | context = {} |
90 | @@ -650,24 +727,7 @@ |
91 | |
92 | context.update({'lang': inv.partner_id.lang}) |
93 | compute_taxes = ait_obj.compute(cr, uid, inv.id, context=context) |
94 | - if not inv.tax_line: |
95 | - for tax in compute_taxes.values(): |
96 | - ait_obj.create(cr, uid, tax) |
97 | - else: |
98 | - tax_key = [] |
99 | - for tax in inv.tax_line: |
100 | - if tax.manual: |
101 | - continue |
102 | - key = (tax.tax_code_id.id, tax.base_code_id.id, tax.account_id.id) |
103 | - tax_key.append(key) |
104 | - if not key in compute_taxes: |
105 | - raise osv.except_osv(_('Warning !'), _('Global taxes defined, but are not in invoice lines !')) |
106 | - base = compute_taxes[key]['base'] |
107 | - if abs(base - tax.base) > inv.company_id.currency_id.rounding: |
108 | - raise osv.except_osv(_('Warning !'), _('Tax base different !\nClick on compute to update tax base')) |
109 | - for key in compute_taxes: |
110 | - if not key in tax_key: |
111 | - raise osv.except_osv(_('Warning !'), _('Taxes missing !')) |
112 | + self.check_tax_lines(cr, uid, inv, compute_taxes, ait_obj) |
113 | |
114 | if inv.type in ('in_invoice', 'in_refund') and abs(inv.check_total - inv.amount_total) >= (inv.currency_id.rounding/2.0): |
115 | raise osv.except_osv(_('Bad total !'), _('Please verify the price of the invoice !\nThe real total does not match the computed total.')) |
116 | @@ -684,24 +744,7 @@ |
117 | # create one move line for the total and possibly adjust the other lines amount |
118 | total = 0 |
119 | total_currency = 0 |
120 | - for i in iml: |
121 | - if inv.currency_id.id != company_currency: |
122 | - i['currency_id'] = inv.currency_id.id |
123 | - i['amount_currency'] = i['price'] |
124 | - i['price'] = cur_obj.compute(cr, uid, inv.currency_id.id, |
125 | - company_currency, i['price'], |
126 | - context={'date': inv.date_invoice or time.strftime('%Y-%m-%d')}) |
127 | - else: |
128 | - i['amount_currency'] = False |
129 | - i['currency_id'] = False |
130 | - i['ref'] = ref |
131 | - if inv.type in ('out_invoice','in_refund'): |
132 | - total += i['price'] |
133 | - total_currency += i['amount_currency'] or i['price'] |
134 | - i['price'] = - i['price'] |
135 | - else: |
136 | - total -= i['price'] |
137 | - total_currency -= i['amount_currency'] or i['price'] |
138 | + total, total_currency, iml = self.compute_invoice_totals(cr, uid, inv, company_currency, ref, iml) |
139 | acc_id = inv.account_id.id |
140 | |
141 | name = inv['name'] or '/' |
142 | @@ -756,26 +799,7 @@ |
143 | |
144 | line = map(lambda x:(0,0,self.line_get_convert(cr, uid, x, part, date, context={})) ,iml) |
145 | |
146 | - if inv.journal_id.group_invoice_lines: |
147 | - line2 = {} |
148 | - for x, y, l in line: |
149 | - tmp = str(l['account_id']) |
150 | - tmp += '-'+str(l.get('tax_code_id',"False")) |
151 | - tmp += '-'+str(l.get('product_id',"False")) |
152 | - tmp += '-'+str(l.get('analytic_account_id',"False")) |
153 | - tmp += '-'+str(l.get('date_maturity',"False")) |
154 | - |
155 | - if tmp in line2: |
156 | - am = line2[tmp]['debit'] - line2[tmp]['credit'] + (l['debit'] - l['credit']) |
157 | - line2[tmp]['debit'] = (am > 0) and am or 0.0 |
158 | - line2[tmp]['credit'] = (am < 0) and -am or 0.0 |
159 | - line2[tmp]['tax_amount'] += l['tax_amount'] |
160 | - line2[tmp]['analytic_lines'] += l['analytic_lines'] |
161 | - else: |
162 | - line2[tmp] = l |
163 | - line = [] |
164 | - for key, val in line2.items(): |
165 | - line.append((0,0,val)) |
166 | + line = self.group_lines(cr, uid, iml, line, inv) |
167 | |
168 | journal_id = inv.journal_id.id #self._get_journal(cr, uid, {'type': inv['type']}) |
169 | journal = self.pool.get('account.journal').browse(cr, uid, journal_id) |
This time the right branch targeting trunk addons. /code.launchpad .net/~openerp- commiter/ openobject- addons/ account- method- extraction/ +merge/ 15727
See original comments here for details: https:/
Notices that I carefully checked that my merge is still compatible with addons by checking that the bits we extract in methods were still present unmodified in trunk where I branched.
BTW, after months of pain, this is the first decent branch submission because Launchpad is finally using stacked branches now that Tiny updated OpenERP branch formats, so uploading this branch took like 1 min vs 3hours previously...