Merge lp:~camptocamp/account-financial-report/6.1_backport_account_export_csv_company_fix into lp:~account-report-core-editor/account-financial-report/6.1
- 6.1_backport_account_export_csv_company_fix
- Merge into 6.1
Status: | Merged |
---|---|
Merged at revision: | 26 |
Proposed branch: | lp:~camptocamp/account-financial-report/6.1_backport_account_export_csv_company_fix |
Merge into: | lp:~account-report-core-editor/account-financial-report/6.1 |
Diff against target: |
754 lines (+710/-0) 8 files modified
account_export_csv/__init__.py (+21/-0) account_export_csv/__openerp__.py (+46/-0) account_export_csv/i18n/account_export_csv.po (+111/-0) account_export_csv/i18n/fr.po (+74/-0) account_export_csv/menu.xml (+16/-0) account_export_csv/wizard/__init__.py (+21/-0) account_export_csv/wizard/account_export_csv.py (+374/-0) account_export_csv/wizard/account_export_csv_view.xml (+47/-0) |
To merge this branch: | bzr merge lp:~camptocamp/account-financial-report/6.1_backport_account_export_csv_company_fix |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Pedro Manuel Baeza | code review | Approve | |
Matthieu Dietrich @ camptocamp | Approve | ||
Guewen Baconnier @ Camptocamp | Pending | ||
Review via email: mp+200836@code.launchpad.net |
This proposal supersedes a proposal from 2014-01-07.
Commit message
Description of the change
Fixing the company_id criteria + adding the last export, Journal Entries.
Pedro Manuel Baeza (pedro.baeza) wrote : Posted in a previous version of this proposal | # |
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : Posted in a previous version of this proposal | # |
The _get_rows_account and _get_rows_analytic methods take a 'company_id' argument, this one is passed to the query, but this one does not use it, so the lines are not multi-company aware.
I'm not sure if it should be done directly in the query or if you should leave the query as is and do a self.search(cr, uid, [('id', 'in', line_ids)], context=context) afterwards to apply the rules.
Guewen Baconnier @ Camptocamp (gbaconnier-c2c) wrote : Posted in a previous version of this proposal | # |
> The _get_rows_account and _get_rows_analytic methods take a 'company_id'
> argument, this one is passed to the query, but this one does not use it, so
> the lines are not multi-company aware.
> I'm not sure if it should be done directly in the query or if you should leave
> the query as is and do a self.search(cr, uid, [('id', 'in', line_ids)],
> context=context) afterwards to apply the rules.
Note that I requested the same fix in the 7.0 branch.
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote : Posted in a previous version of this proposal | # |
No changes since 2013-08-30 after Need Fixing request -> I set this in WIP
@invitu
Please do the required changes then set it in Needs Review again
Cheers,
Yannick
Matthieu Dietrich @ camptocamp (mdietrich-c2c) wrote : Posted in a previous version of this proposal | # |
Okay, I tried re-submitting using the same proposal (but a different branch), and the branch was not changed.
What I wanted to do is use lp:~camptocamp/account-financial-report/6.1_backport_account_export_csv_company_fix/; it contains invitu's backport, as well as the required fix on company_id and an additional backport for the last report, Journal Entries.
Matthieu Dietrich @ camptocamp (mdietrich-c2c) wrote : | # |
Okay, managed to (finally) resubmit this correctly.
Pedro Manuel Baeza (pedro.baeza) wrote : | # |
The new revision seems OK.
Preview Diff
1 | === added directory 'account_export_csv' |
2 | === added file 'account_export_csv/__init__.py' |
3 | --- account_export_csv/__init__.py 1970-01-01 00:00:00 +0000 |
4 | +++ account_export_csv/__init__.py 2014-01-08 13:43:08 +0000 |
5 | @@ -0,0 +1,21 @@ |
6 | +# -*- coding: utf-8 -*- |
7 | +############################################################################## |
8 | +# |
9 | +# Author Joel Grand-Guillaume and Vincent Renaville Copyright 2013 Camptocamp SA |
10 | +# |
11 | +# This program is free software: you can redistribute it and/or modify |
12 | +# it under the terms of the GNU Affero General Public License as |
13 | +# published by the Free Software Foundation, either version 3 of the |
14 | +# License, or (at your option) any later version. |
15 | +# |
16 | +# This program is distributed in the hope that it will be useful, |
17 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | +# GNU Affero General Public License for more details. |
20 | +# |
21 | +# You should have received a copy of the GNU Affero General Public License |
22 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
23 | +# |
24 | +############################################################################## |
25 | + |
26 | +import wizard |
27 | \ No newline at end of file |
28 | |
29 | === added file 'account_export_csv/__openerp__.py' |
30 | --- account_export_csv/__openerp__.py 1970-01-01 00:00:00 +0000 |
31 | +++ account_export_csv/__openerp__.py 2014-01-08 13:43:08 +0000 |
32 | @@ -0,0 +1,46 @@ |
33 | +# -*- coding: utf-8 -*- |
34 | +############################################################################## |
35 | +# |
36 | +# Author Joel Grand-Guillaume and Vincent Renaville Copyright 2013 Camptocamp SA |
37 | +# |
38 | +# This program is free software: you can redistribute it and/or modify |
39 | +# it under the terms of the GNU Affero General Public License as |
40 | +# published by the Free Software Foundation, either version 3 of the |
41 | +# License, or (at your option) any later version. |
42 | +# |
43 | +# This program is distributed in the hope that it will be useful, |
44 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
45 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
46 | +# GNU Affero General Public License for more details. |
47 | +# |
48 | +# You should have received a copy of the GNU Affero General Public License |
49 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
50 | +# |
51 | +############################################################################## |
52 | + |
53 | +{ |
54 | + 'name' : 'Account Export CSV', |
55 | + 'version' : '1', |
56 | + 'depends' : [ |
57 | + 'account', |
58 | + ], |
59 | + 'author' : 'Camptocamp', |
60 | + 'description': """ |
61 | + |
62 | + Add a wizard that allow you to export a csv file based on accounting journal entries |
63 | + |
64 | + - Trial Balance |
65 | + - Analytic Balance (with accounts) |
66 | + |
67 | + You can filter by period |
68 | + |
69 | + |
70 | + """, |
71 | + 'website': 'http://www.camptocamp.com', |
72 | + 'data': [ |
73 | + 'wizard/account_export_csv_view.xml', |
74 | + 'menu.xml', |
75 | + ], |
76 | + 'installable': True, |
77 | + 'active': False, |
78 | +} |
79 | |
80 | === added directory 'account_export_csv/i18n' |
81 | === added file 'account_export_csv/i18n/account_export_csv.po' |
82 | --- account_export_csv/i18n/account_export_csv.po 1970-01-01 00:00:00 +0000 |
83 | +++ account_export_csv/i18n/account_export_csv.po 2014-01-08 13:43:08 +0000 |
84 | @@ -0,0 +1,111 @@ |
85 | +# Translation of OpenERP Server. |
86 | +# This file contains the translation of the following modules: |
87 | +# * account_export_csv |
88 | +# |
89 | +msgid "" |
90 | +msgstr "" |
91 | +"Project-Id-Version: OpenERP Server 7.0\n" |
92 | +"Report-Msgid-Bugs-To: \n" |
93 | +"POT-Creation-Date: 2013-04-10 15:11+0000\n" |
94 | +"PO-Revision-Date: 2013-04-10 15:11+0000\n" |
95 | +"Last-Translator: <>\n" |
96 | +"Language-Team: \n" |
97 | +"MIME-Version: 1.0\n" |
98 | +"Content-Type: text/plain; charset=UTF-8\n" |
99 | +"Content-Transfer-Encoding: \n" |
100 | +"Plural-Forms: \n" |
101 | + |
102 | +#. module: account_export_csv |
103 | +#: model:ir.model,name:account_export_csv.model_account_csv_export |
104 | +msgid "Export Accounting" |
105 | +msgstr "" |
106 | + |
107 | +#. module: account_export_csv |
108 | +#: field:account.csv.export,export_filename:0 |
109 | +msgid "Export CSV Filename" |
110 | +msgstr "" |
111 | + |
112 | +#. module: account_export_csv |
113 | +#: view:account.csv.export:0 |
114 | +msgid "Trial Balance" |
115 | +msgstr "" |
116 | + |
117 | +#. module: account_export_csv |
118 | +#: field:account.csv.export,company_id:0 |
119 | +msgid "Company" |
120 | +msgstr "" |
121 | + |
122 | +#. module: account_export_csv |
123 | +#: view:account.csv.export:0 |
124 | +msgid "Analytic Balance (with accounts)" |
125 | +msgstr "" |
126 | + |
127 | +#. module: account_export_csv |
128 | +#: help:account.csv.export,periods:0 |
129 | +msgid "All periods in the fiscal year if empty" |
130 | +msgstr "" |
131 | + |
132 | +#. module: account_export_csv |
133 | +#: field:account.csv.export,periods:0 |
134 | +msgid "Periods" |
135 | +msgstr "" |
136 | + |
137 | +#. module: account_export_csv |
138 | +#: view:account.csv.export:0 |
139 | +msgid "Close" |
140 | +msgstr "" |
141 | + |
142 | +#. module: account_export_csv |
143 | +#: view:account.csv.export:0 |
144 | +#: model:ir.actions.act_window,name:account_export_csv.action_account_csv_export |
145 | +#: model:ir.ui.menu,name:account_export_csv.menu_account_csv_export |
146 | +msgid "Accounting CSV Export" |
147 | +msgstr "" |
148 | + |
149 | +#. module: account_export_csv |
150 | +#: field:account.csv.export,data:0 |
151 | +msgid "CSV" |
152 | +msgstr "" |
153 | + |
154 | +#. module: account_export_csv |
155 | +#: field:account.csv.export,fiscalyear_id:0 |
156 | +msgid "Fiscalyear" |
157 | +msgstr "" |
158 | + |
159 | +#. module: account_export_csv |
160 | +#: view:account.csv.export:0 |
161 | +msgid "Analytic Balance (with accounts)" |
162 | +msgstr "" |
163 | + |
164 | +#. module: account_export_csv |
165 | +#: field:account.csv.export,stop_period_id:0 |
166 | +msgid "End period" |
167 | +msgstr "" |
168 | + |
169 | +#. module: account_export_csv |
170 | +#: view:account.csv.export:0 |
171 | +msgid "Close" |
172 | +msgstr "" |
173 | + |
174 | +#. module: account_export_csv |
175 | +#: view:account.csv.export:0 |
176 | +#: model:ir.actions.act_window,name:account_export_csv.action_account_csv_export |
177 | +#: model:ir.ui.menu,name:account_export_csv.menu_account_csv_export |
178 | +msgid "Accounting CSV Export" |
179 | +msgstr "" |
180 | + |
181 | +#. module: account_export_csv |
182 | +#: field:account.csv.export,data:0 |
183 | +msgid "CSV" |
184 | +msgstr "" |
185 | + |
186 | +#. module: account_export_csv |
187 | +#: model:ir.model,name:account_export_csv.model_account_csv_export |
188 | +msgid "Export Accounting Entries" |
189 | +msgstr "" |
190 | + |
191 | +#. module: account_export_csv |
192 | +#: field:account.csv.export,fiscalyear_id:0 |
193 | +msgid "Fiscalyear" |
194 | +msgstr "" |
195 | + |
196 | |
197 | === added file 'account_export_csv/i18n/fr.po' |
198 | --- account_export_csv/i18n/fr.po 1970-01-01 00:00:00 +0000 |
199 | +++ account_export_csv/i18n/fr.po 2014-01-08 13:43:08 +0000 |
200 | @@ -0,0 +1,74 @@ |
201 | +# Translation of OpenERP Server. |
202 | +# This file contains the translation of the following modules: |
203 | +# * account_export_csv |
204 | +# |
205 | +msgid "" |
206 | +msgstr "" |
207 | +"Project-Id-Version: OpenERP Server 7.0\n" |
208 | +"Report-Msgid-Bugs-To: \n" |
209 | +"POT-Creation-Date: 2013-04-10 15:11+0000\n" |
210 | +"PO-Revision-Date: 2013-04-10 15:11+0000\n" |
211 | +"Last-Translator: <>\n" |
212 | +"Language-Team: \n" |
213 | +"MIME-Version: 1.0\n" |
214 | +"Content-Type: text/plain; charset=UTF-8\n" |
215 | +"Content-Transfer-Encoding: \n" |
216 | +"Plural-Forms: \n" |
217 | + |
218 | +#. module: account_export_csv |
219 | +#: model:ir.model,name:account_export_csv.model_account_csv_export |
220 | +msgid "Export Accounting" |
221 | +msgstr "Export comptable" |
222 | + |
223 | +#. module: account_export_csv |
224 | +#: field:account.csv.export,export_filename:0 |
225 | +msgid "Export CSV Filename" |
226 | +msgstr "Nom du fichier CSV d'export" |
227 | + |
228 | +#. module: account_export_csv |
229 | +#: view:account.csv.export:0 |
230 | +msgid "Trial Balance" |
231 | +msgstr "Balance générale" |
232 | + |
233 | +#. module: account_export_csv |
234 | +#: field:account.csv.export,company_id:0 |
235 | +msgid "Company" |
236 | +msgstr "Société" |
237 | + |
238 | +#. module: account_export_csv |
239 | +#: view:account.csv.export:0 |
240 | +msgid "Analytic Balance (with accounts)" |
241 | +msgstr "Balance analytique (avec comptes)" |
242 | + |
243 | +#. module: account_export_csv |
244 | +#: help:account.csv.export,periods:0 |
245 | +msgid "All periods in the fiscal year if empty" |
246 | +msgstr "Toutes les périodes de l'année fiscale si vide" |
247 | + |
248 | +#. module: account_export_csv |
249 | +#: field:account.csv.export,periods:0 |
250 | +msgid "Periods" |
251 | +msgstr "Périodes" |
252 | + |
253 | +#. module: account_export_csv |
254 | +#: view:account.csv.export:0 |
255 | +msgid "Close" |
256 | +msgstr "Fermer" |
257 | + |
258 | +#. module: account_export_csv |
259 | +#: view:account.csv.export:0 |
260 | +#: model:ir.actions.act_window,name:account_export_csv.action_account_csv_export |
261 | +#: model:ir.ui.menu,name:account_export_csv.menu_account_csv_export |
262 | +msgid "Accounting CSV Export" |
263 | +msgstr "Export comptable CSV" |
264 | + |
265 | +#. module: account_export_csv |
266 | +#: field:account.csv.export,data:0 |
267 | +msgid "CSV" |
268 | +msgstr "CSV" |
269 | + |
270 | +#. module: account_export_csv |
271 | +#: field:account.csv.export,fiscalyear_id:0 |
272 | +msgid "Fiscalyear" |
273 | +msgstr "Année fiscale" |
274 | + |
275 | |
276 | === added file 'account_export_csv/menu.xml' |
277 | --- account_export_csv/menu.xml 1970-01-01 00:00:00 +0000 |
278 | +++ account_export_csv/menu.xml 2014-01-08 13:43:08 +0000 |
279 | @@ -0,0 +1,16 @@ |
280 | +<?xml version="1.0" encoding="utf-8"?> |
281 | +<openerp> |
282 | + <data> |
283 | + |
284 | + <menuitem |
285 | + icon="STOCK_EXECUTE" |
286 | + name="Accounting CSV Export" |
287 | + action="action_account_csv_export" |
288 | + id="menu_account_csv_export" |
289 | + parent="account.final_accounting_reports" |
290 | + sequence="110" |
291 | + /> |
292 | + |
293 | + |
294 | + </data> |
295 | +</openerp> |
296 | |
297 | === added directory 'account_export_csv/wizard' |
298 | === added file 'account_export_csv/wizard/__init__.py' |
299 | --- account_export_csv/wizard/__init__.py 1970-01-01 00:00:00 +0000 |
300 | +++ account_export_csv/wizard/__init__.py 2014-01-08 13:43:08 +0000 |
301 | @@ -0,0 +1,21 @@ |
302 | +# -*- coding: utf-8 -*- |
303 | +############################################################################## |
304 | +# |
305 | +# Author Joel Grand-Guillaume and Vincent Renaville Copyright 2013 Camptocamp SA |
306 | +# |
307 | +# This program is free software: you can redistribute it and/or modify |
308 | +# it under the terms of the GNU Affero General Public License as |
309 | +# published by the Free Software Foundation, either version 3 of the |
310 | +# License, or (at your option) any later version. |
311 | +# |
312 | +# This program is distributed in the hope that it will be useful, |
313 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
314 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
315 | +# GNU Affero General Public License for more details. |
316 | +# |
317 | +# You should have received a copy of the GNU Affero General Public License |
318 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
319 | +# |
320 | +############################################################################## |
321 | + |
322 | +import account_export_csv |
323 | \ No newline at end of file |
324 | |
325 | === added file 'account_export_csv/wizard/account_export_csv.py' |
326 | --- account_export_csv/wizard/account_export_csv.py 1970-01-01 00:00:00 +0000 |
327 | +++ account_export_csv/wizard/account_export_csv.py 2014-01-08 13:43:08 +0000 |
328 | @@ -0,0 +1,374 @@ |
329 | +# -*- coding: utf-8 -*- |
330 | +############################################################################## |
331 | +# |
332 | +# Author Joel Grand-Guillaume and Vincent Renaville Copyright 2013 Camptocamp SA |
333 | +# CSV data formating inspired from http://docs.python.org/2.7/library/csv.html?highlight=csv#examples |
334 | +# |
335 | +# This program is free software: you can redistribute it and/or modify |
336 | +# it under the terms of the GNU Affero General Public License as |
337 | +# published by the Free Software Foundation, either version 3 of the |
338 | +# License, or (at your option) any later version. |
339 | +# |
340 | +# This program is distributed in the hope that it will be useful, |
341 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
342 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
343 | +# GNU Affero General Public License for more details. |
344 | +# |
345 | +# You should have received a copy of the GNU Affero General Public License |
346 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
347 | +# |
348 | +############################################################################## |
349 | + |
350 | +import time |
351 | +import StringIO |
352 | +import cStringIO |
353 | +import base64 |
354 | + |
355 | +import csv |
356 | +import codecs |
357 | + |
358 | +from openerp.osv import orm, fields |
359 | +from openerp.tools.translate import _ |
360 | + |
361 | + |
362 | +class AccountUnicodeWriter(object): |
363 | + """ |
364 | + A CSV writer which will write rows to CSV file "f", |
365 | + which is encoded in the given encoding. |
366 | + """ |
367 | + |
368 | + def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds): |
369 | + # Redirect output to a queue |
370 | + self.queue = cStringIO.StringIO() |
371 | + # created a writer with Excel formating settings |
372 | + self.writer = csv.writer(self.queue, dialect=dialect, **kwds) |
373 | + self.stream = f |
374 | + self.encoder = codecs.getincrementalencoder(encoding)() |
375 | + |
376 | + def writerow(self, row): |
377 | + #we ensure that we do not try to encode none or bool |
378 | + row = [x or u'' for x in row] |
379 | + |
380 | + encoded_row = [] |
381 | + for c in row: |
382 | + if type(c) == unicode: |
383 | + encoded_row.append(c.encode("utf-8")) |
384 | + else: |
385 | + encoded_row.append(c) |
386 | + |
387 | + self.writer.writerow(encoded_row) |
388 | + # Fetch UTF-8 output from the queue ... |
389 | + data = self.queue.getvalue() |
390 | + data = data.decode("utf-8") |
391 | + # ... and reencode it into the target encoding |
392 | + data = self.encoder.encode(data) |
393 | + # write to the target stream |
394 | + self.stream.write(data) |
395 | + # empty queue |
396 | + self.queue.truncate(0) |
397 | + |
398 | + def writerows(self, rows): |
399 | + for row in rows: |
400 | + self.writerow(row) |
401 | + |
402 | +class AccountCSVExport(orm.TransientModel): |
403 | + _name = 'account.csv.export' |
404 | + _description = 'Export Accounting' |
405 | + |
406 | + _columns = { |
407 | + 'data': fields.binary('CSV',readonly=True), |
408 | + 'company_id': fields.many2one('res.company', 'Company', invisible=True), |
409 | + 'fiscalyear_id': fields.many2one('account.fiscalyear', 'Fiscalyear', required=True), |
410 | + 'periods': fields.many2many('account.period','rel_wizard_period','wizard_id','period_id','Periods',help='All periods in the fiscal year if empty'), |
411 | + 'journal_ids': fields.many2many('account.journal','rel_wizard_journal','wizard_id','journal_id','Journals', help='If empty, use all journals, only used for journal entries'), |
412 | + 'export_filename': fields.char('Export CSV Filename', size=128), |
413 | + } |
414 | + |
415 | + def _get_company_default(self, cr, uid, context=None): |
416 | + comp_obj = self.pool['res.company'] |
417 | + return comp_obj._company_default_get(cr, uid, 'account.fiscalyear', context=context) |
418 | + |
419 | + def _get_fiscalyear_default(self, cr, uid, context=None): |
420 | + fiscalyear_obj = self.pool['account.fiscalyear'] |
421 | + context['company_id'] = self._get_company_default(cr, uid, context) |
422 | + return fiscalyear_obj.find(cr,uid,dt=None,exception=True, context=context) |
423 | + |
424 | + _defaults = {'company_id': _get_company_default, |
425 | + 'fiscalyear_id' : _get_fiscalyear_default, |
426 | + 'export_filename' : 'account_export.csv'} |
427 | + |
428 | + def action_manual_export_account(self, cr, uid, ids, context=None): |
429 | + this = self.browse(cr, uid, ids)[0] |
430 | + rows = self.get_data(cr, uid, ids,"account", context) |
431 | + file_data = StringIO.StringIO() |
432 | + try: |
433 | + writer = AccountUnicodeWriter(file_data) |
434 | + writer.writerows(rows) |
435 | + file_value = file_data.getvalue() |
436 | + self.write(cr, uid, ids, |
437 | + {'data': base64.encodestring(file_value)}, |
438 | + context=context) |
439 | + finally: |
440 | + file_data.close() |
441 | + return { |
442 | + 'type': 'ir.actions.act_window', |
443 | + 'res_model': 'account.csv.export', |
444 | + 'view_mode': 'form', |
445 | + 'view_type': 'form', |
446 | + 'res_id': this.id, |
447 | + 'views': [(False, 'form')], |
448 | + 'target': 'new', |
449 | + } |
450 | + |
451 | + |
452 | + def _get_header_account(self, cr, uid, ids, context=None): |
453 | + return [_(u'CODE'), |
454 | + _(u'NAME'), |
455 | + _(u'DEBIT'), |
456 | + _(u'CREDIT'), |
457 | + _(u'BALANCE'), |
458 | + ] |
459 | + |
460 | + def _get_rows_account(self, cr, uid, ids, fiscalyear_id,period_range_ids,journal_ids,company_id,context=None): |
461 | + """ |
462 | + Return list to generate rows of the CSV file |
463 | + """ |
464 | + cr.execute(""" |
465 | + select ac.code,ac.name, |
466 | + sum(debit) as sum_debit,sum(credit) as sum_credit,sum(debit) - sum(credit) as balance |
467 | + from account_move_line as aml,account_account as ac |
468 | + where aml.account_id = ac.id |
469 | + and period_id in %(period_ids)s |
470 | + and aml.company_id = %(company_id)s |
471 | + group by ac.id,ac.code,ac.name |
472 | + order by ac.code |
473 | + """, |
474 | + {'fiscalyear_id': fiscalyear_id,'company_id':company_id,'period_ids':tuple(period_range_ids)} |
475 | + ) |
476 | + res = cr.fetchall() |
477 | + |
478 | + rows = [] |
479 | + for line in res: |
480 | + rows.append(list(line)) |
481 | + return rows |
482 | + |
483 | + def action_manual_export_analytic(self, cr, uid, ids, context=None): |
484 | + this = self.browse(cr, uid, ids)[0] |
485 | + rows = self.get_data(cr, uid, ids,"analytic", context) |
486 | + file_data = StringIO.StringIO() |
487 | + try: |
488 | + writer = AccountUnicodeWriter(file_data) |
489 | + writer.writerows(rows) |
490 | + file_value = file_data.getvalue() |
491 | + self.write(cr, uid, ids, |
492 | + {'data': base64.encodestring(file_value)}, |
493 | + context=context) |
494 | + finally: |
495 | + file_data.close() |
496 | + return { |
497 | + 'type': 'ir.actions.act_window', |
498 | + 'res_model': 'account.csv.export', |
499 | + 'view_mode': 'form', |
500 | + 'view_type': 'form', |
501 | + 'res_id': this.id, |
502 | + 'views': [(False, 'form')], |
503 | + 'target': 'new', |
504 | + } |
505 | + |
506 | + def _get_header_analytic(self, cr, uid, ids, context=None): |
507 | + return [_(u'ANALYTIC CODE'), |
508 | + _(u'ANALYTIC NAME'), |
509 | + _(u'CODE'), |
510 | + _(u'ACCOUNT NAME'), |
511 | + _(u'DEBIT'), |
512 | + _(u'CREDIT'), |
513 | + _(u'BALANCE'), |
514 | + ] |
515 | + |
516 | + def _get_rows_analytic(self, cr, uid, ids, fiscalyear_id,period_range_ids,journal_ids,company_id,context=None): |
517 | + """ |
518 | + Return list to generate rows of the CSV file |
519 | + """ |
520 | + cr.execute(""" select aac.code as analytic_code,aac.name as analytic_name,ac.code,ac.name, |
521 | + sum(debit) as sum_debit,sum(credit) as sum_credit,sum(debit) - sum(credit) as balance |
522 | + from account_move_line |
523 | + left outer join account_analytic_account as aac |
524 | + on (account_move_line.analytic_account_id = aac.id) |
525 | + inner join account_account as ac |
526 | + on account_move_line.account_id = ac.id |
527 | + and account_move_line.period_id in %(period_ids)s |
528 | + and account_move_line.company_id = %(company_id)s |
529 | + group by aac.id,aac.code,aac.name,ac.id,ac.code,ac.name |
530 | + order by aac.code |
531 | + """, |
532 | + {'fiscalyear_id': fiscalyear_id,'company_id':company_id,'period_ids':tuple(period_range_ids)} |
533 | + ) |
534 | + res = cr.fetchall() |
535 | + |
536 | + rows = [] |
537 | + for line in res: |
538 | + rows.append(list(line)) |
539 | + return rows |
540 | + |
541 | + def action_manual_export_journal_entries(self, cr, uid, ids, context=None): |
542 | + """ |
543 | + Here we use TemporaryFile to avoid full filling the OpenERP worker Memory |
544 | + We also write the data to the wizard with SQL query as write seams to use |
545 | + too much memory as well. |
546 | + |
547 | + Those improvements permitted to improve the export from a 100k line to 200k lines |
548 | + with default `limit_memory_hard = 805306368` (768MB) with more lines, |
549 | + you might encounter a MemoryError when trying to download the file even |
550 | + if it has been generated. |
551 | + |
552 | + To be able to export bigger volume of data, it is advised to set |
553 | + limit_memory_hard to 2097152000 (2 GB) to generate the file and let |
554 | + OpenERP load it in the wizard when trying to download it. |
555 | + |
556 | + Tested with up to a generation of 700k entry lines |
557 | + """ |
558 | + this = self.browse(cr, uid, ids)[0] |
559 | + rows = self.get_data(cr, uid, ids, "journal_entries", context) |
560 | + file_data = StringIO.StringIO() |
561 | + try: |
562 | + writer = AccountUnicodeWriter(file_data) |
563 | + writer.writerows(rows) |
564 | + file_value = file_data.getvalue() |
565 | + self.write(cr, uid, ids, |
566 | + {'data': base64.encodestring(file_value)}, |
567 | + context=context) |
568 | + finally: |
569 | + file_data.close() |
570 | + return { |
571 | + 'type': 'ir.actions.act_window', |
572 | + 'res_model': 'account.csv.export', |
573 | + 'view_mode': 'form', |
574 | + 'view_type': 'form', |
575 | + 'res_id': this.id, |
576 | + 'views': [(False, 'form')], |
577 | + 'target': 'new', |
578 | + } |
579 | + |
580 | + |
581 | + def _get_header_journal_entries(self, cr, uid, ids, context=None): |
582 | + |
583 | + return [ |
584 | + # Standard Sage export fields |
585 | + _(u'DATE'), |
586 | + _(u'JOURNAL CODE'), |
587 | + _(u'ACCOUNT CODE'), |
588 | + _(u'PARTNER NAME'), |
589 | + _(u'REF'), |
590 | + _(u'DESCRIPTION'), |
591 | + _(u'DEBIT'), |
592 | + _(u'CREDIT'), |
593 | + _(u'FULL RECONCILE'), |
594 | + _(u'PARTIAL RECONCILE'), |
595 | + _(u'ANALYTIC ACCOUNT CODE'), |
596 | + |
597 | + # Other fields |
598 | + _(u'ENTRY NUMBER'), |
599 | + _(u'ACCOUNT NAME'), |
600 | + _(u'BALANCE'), |
601 | + _(u'AMOUNT CURRENCY'), |
602 | + _(u'CURRENCY'), |
603 | + _(u'ANALYTIC ACCOUNT NAME'), |
604 | + _(u'JOURNAL'), |
605 | + _(u'MONTH'), |
606 | + _(u'FISCAL YEAR'), |
607 | + _(u'TAX CODE CODE'), |
608 | + _(u'TAX CODE NAME'), |
609 | + _(u'TAX AMOUNT'), |
610 | + ] |
611 | + |
612 | + |
613 | + def _get_rows_journal_entries(self, cr, uid, ids, |
614 | + fiscalyear_id, |
615 | + period_range_ids, |
616 | + journal_ids, |
617 | + company_id, |
618 | + context=None): |
619 | + print period_range_ids |
620 | + print journal_ids |
621 | + """ |
622 | + Create a generator of rows of the CSV file |
623 | + """ |
624 | + cr.execute(""" |
625 | + SELECT |
626 | + account_move_line.date AS date, |
627 | + account_journal.name as journal, |
628 | + account_account.code AS account_code, |
629 | + res_partner.name AS partner_name, |
630 | + account_move_line.ref AS ref, |
631 | + account_move_line.name AS description, |
632 | + account_move_line.debit AS debit, |
633 | + account_move_line.credit AS credit, |
634 | + account_move_reconcile.name as full_reconcile, |
635 | + account_move_line.reconcile_partial_id AS partial_reconcile_id, |
636 | + account_analytic_account.code AS analytic_account_code, |
637 | + |
638 | + account_move.name AS entry_number, |
639 | + account_account.name AS account_name, |
640 | + account_move_line.debit - account_move_line.credit AS balance, |
641 | + account_move_line.amount_currency AS amount_currency, |
642 | + res_currency.name AS currency, |
643 | + account_analytic_account.name AS analytic_account_name, |
644 | + account_journal.name as journal, |
645 | + account_period.code AS month, |
646 | + account_fiscalyear.name as fiscal_year, |
647 | + account_tax_code.code AS aml_tax_code_code, |
648 | + account_tax_code.name AS aml_tax_code_name, |
649 | + account_move_line.tax_amount AS aml_tax_amount |
650 | + FROM |
651 | + public.account_move_line |
652 | + JOIN account_account on (account_account.id=account_move_line.account_id) |
653 | + JOIN account_period on (account_period.id=account_move_line.period_id) |
654 | + JOIN account_fiscalyear on (account_fiscalyear.id=account_period.fiscalyear_id) |
655 | + JOIN account_journal on (account_journal.id = account_move_line.journal_id) |
656 | + LEFT JOIN res_currency on (res_currency.id=account_move_line.currency_id) |
657 | + LEFT JOIN account_move_reconcile on (account_move_reconcile.id = account_move_line.reconcile_id) |
658 | + LEFT JOIN res_partner on (res_partner.id=account_move_line.partner_id) |
659 | + LEFT JOIN account_move on (account_move.id=account_move_line.move_id) |
660 | + LEFT JOIN account_tax on (account_tax.id=account_move_line.account_tax_id) |
661 | + LEFT JOIN account_tax_code on (account_tax_code.id=account_move_line.tax_code_id) |
662 | + LEFT JOIN account_analytic_account on (account_analytic_account.id=account_move_line.analytic_account_id) |
663 | + WHERE account_period.id IN %(period_ids)s |
664 | + AND account_journal.id IN %(journal_ids)s |
665 | + AND account_move_line.company_id = %(company_id)s |
666 | + ORDER BY account_move_line.date |
667 | + """, |
668 | + {'period_ids': tuple(period_range_ids), 'journal_ids': tuple(journal_ids), 'company_id': company_id} |
669 | + ) |
670 | + while 1: |
671 | + # http://initd.org/psycopg/docs/cursor.html#cursor.fetchmany |
672 | + # Set cursor.arraysize to minimize network round trips |
673 | + cr.arraysize=100 |
674 | + rows = cr.fetchmany() |
675 | + if not rows: |
676 | + break |
677 | + for row in rows: |
678 | + yield row |
679 | + |
680 | + def get_data(self, cr, uid, ids,result_type,context=None): |
681 | + get_header_func = getattr(self,("_get_header_%s"%(result_type)), None) |
682 | + get_rows_func = getattr(self,("_get_rows_%s"%(result_type)), None) |
683 | + form = self.browse(cr, uid, ids[0], context=context) |
684 | + fiscalyear_id = form.fiscalyear_id.id |
685 | + user_obj = self.pool.get('res.users') |
686 | + company_id = user_obj.browse(cr, uid, uid).company_id.id |
687 | + if form.periods: |
688 | + period_range_ids = [x.id for x in form.periods] |
689 | + else: |
690 | + # If not period selected , we take all periods |
691 | + p_obj = self.pool.get("account.period") |
692 | + period_range_ids = p_obj.search(cr,uid,[('fiscalyear_id','=',fiscalyear_id)],context=context) |
693 | + journal_ids = None |
694 | + if form.journal_ids: |
695 | + journal_ids = [x.id for x in form.journal_ids] |
696 | + else: |
697 | + j_obj = self.pool.get("account.journal") |
698 | + journal_ids = j_obj.search(cr, uid, [], context=context) |
699 | + rows = [] |
700 | + rows.append(get_header_func(cr, uid, ids, context=context)) |
701 | + rows.extend(get_rows_func(cr, uid, ids, fiscalyear_id,period_range_ids,journal_ids,company_id, context=context)) |
702 | + return rows |
703 | |
704 | === added file 'account_export_csv/wizard/account_export_csv_view.xml' |
705 | --- account_export_csv/wizard/account_export_csv_view.xml 1970-01-01 00:00:00 +0000 |
706 | +++ account_export_csv/wizard/account_export_csv_view.xml 2014-01-08 13:43:08 +0000 |
707 | @@ -0,0 +1,47 @@ |
708 | +<?xml version="1.0" encoding="utf-8"?> |
709 | +<openerp> |
710 | + <data> |
711 | + |
712 | + <record id="account_csv_export_view" model="ir.ui.view"> |
713 | + <field name="name">Accounting Entries CSV Export</field> |
714 | + <field name="model">account.csv.export</field> |
715 | + <field name="type">form</field> |
716 | + <field name="arch" type="xml"> |
717 | + <form string="Accounting CSV Export"> |
718 | + <group colspan="4"> |
719 | + <field name="company_id" /> |
720 | + <field name="fiscalyear_id" domain="[('company_id', '=', company_id)]"/> |
721 | + </group> |
722 | + <group colspan="4" col="2"> |
723 | + <field name="periods" domain="[('state', '=', 'draft'),('fiscalyear_id','=',fiscalyear_id)]"/> |
724 | + <field name="journal_ids"/> |
725 | + </group> |
726 | + <separator string ="" colspan="4"/> |
727 | + <group colspan="4" col="3"> |
728 | + <button special="cancel" string="Close" icon="gtk-cancel"/> |
729 | + <button name="action_manual_export_account" string="Trial Balance" type="object" icon="gtk-execute"/> |
730 | + <button name="action_manual_export_analytic" string="Analytic Balance (with accounts)" type="object" icon="gtk-execute"/> |
731 | + <button name="action_manual_export_journal_entries" string="Journal Entries" type="object" icon="gtk-execute"/> |
732 | + </group> |
733 | + <separator string ="" colspan="4"/> |
734 | + <group colspan="4"> |
735 | + <field name="data" filename="export_filename"/> |
736 | + </group> |
737 | + |
738 | + </form> |
739 | + </field> |
740 | + </record> |
741 | + |
742 | + <record id="action_account_csv_export" model="ir.actions.act_window"> |
743 | + <field name="name">Accounting CSV Export</field> |
744 | + <field name="res_model">account.csv.export</field> |
745 | + <field name="type">ir.actions.act_window</field> |
746 | + <field name="view_type">form</field> |
747 | + <field name="view_mode">tree,form</field> |
748 | + <field name="view_id" ref="account_csv_export_view"/> |
749 | + <field name="context">{}</field> |
750 | + <field name="target">new</field> |
751 | + </record> |
752 | + |
753 | + </data> |
754 | +</openerp> |
Works like a charm, although the save as "trick" is a little confusing from user perspective.