~unifield-team/unifield-wm/us-826

1539.26.2 by Olivier DOSSMANN
[WIP] Data migration for accounting lines
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
##############################################################################
4
#
5
#    OpenERP, Open Source Management Solution
6
#    Copyright (C) 2011 TeMPO Consulting, MSF. All Rights Reserved
7
#    Developer: Olivier DOSSMANN
8
#
9
#    This program is free software: you can redistribute it and/or modify
10
#    it under the terms of the GNU Affero General Public License as
11
#    published by the Free Software Foundation, either version 3 of the
12
#    License, or (at your option) any later version.
13
#
14
#    This program is distributed in the hope that it will be useful,
15
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
16
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
#    GNU Affero General Public License for more details.
18
#
19
#    You should have received a copy of the GNU Affero General Public License
20
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
#
22
##############################################################################
23
24
from osv import osv
25
from osv import fields
26
from tools.translate import _
27
from time import strftime
28
from tempfile import NamedTemporaryFile
29
from base64 import decodestring
30
from spreadsheet_xml.spreadsheet_xml import SpreadsheetXML
31
from csv import DictReader
1638.8.2 by Olivier DOSSMANN
UF-1991 [ADD] New behaviour for Migration entries:
32
import threading
33
import pooler
1539.26.2 by Olivier DOSSMANN
[WIP] Data migration for accounting lines
34
35
class msf_doc_import_accounting(osv.osv_memory):
36
    _name = 'msf.doc.import.accounting'
37
38
    _columns = {
39
        'date': fields.date(string="Migration date", required=True),
40
        'file': fields.binary(string="File", filters='*.xml, *.xls', required=True),
41
        'filename': fields.char(string="Imported filename", size=256),
1638.8.2 by Olivier DOSSMANN
UF-1991 [ADD] New behaviour for Migration entries:
42
        'progression': fields.float(string="Progression", readonly=True),
43
        'message': fields.char(string="Message", size=256, readonly=True),
44
        'state': fields.selection([('draft', 'Created'), ('inprogress', 'In Progress'), ('error', 'Error'), ('done', 'Done')], string="State", readonly=True, required=True),
45
        'error_ids': fields.one2many('msf.doc.import.accounting.errors', 'wizard_id', "Errors", readonly=True),
1539.26.2 by Olivier DOSSMANN
[WIP] Data migration for accounting lines
46
    }
47
48
    _defaults = {
49
        'date': lambda *a: strftime('%Y-%m-%d'),
1638.8.2 by Olivier DOSSMANN
UF-1991 [ADD] New behaviour for Migration entries:
50
        'progression': lambda *a: 0.0,
51
        'state': lambda *a: 'draft',
1638.8.11 by Olivier DOSSMANN
UF-1991 [UP] Upgrade translations for msf_doc_import/account.py file into fr_MF.po file
52
        'message': lambda *a: _('Initialization…'),
1539.26.2 by Olivier DOSSMANN
[WIP] Data migration for accounting lines
53
    }
54
1539.26.9 by Olivier DOSSMANN
UF-1894 [ADD] Write journal entries and journal items from migration data
55
    def create_entries(self, cr, uid, ids, context=None):
56
        """
57
        Create journal entry 
58
        """
59
        # Checks
60
        if not context:
61
            context = {}
62
        # Prepare some values
1832.1.1 by Olivier DOSSMANN
UF-2181 [FIX] Missing "is_current_instance" for account journal in Unifield
63
        journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'migration'), ('is_current_instance', '=', True)])
1539.26.9 by Olivier DOSSMANN
UF-1894 [ADD] Write journal entries and journal items from migration data
64
        if not journal_ids:
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
65
            raise osv.except_osv(_('Warning'), _('No migration journal found!'))
1539.26.9 by Olivier DOSSMANN
UF-1894 [ADD] Write journal entries and journal items from migration data
66
        journal_id = journal_ids[0]
1539.26.10 by Olivier DOSSMANN
UF-1894 [IMP] Import
67
        # Fetch default funding pool: MSF Private Fund
68
        try: 
69
            msf_fp_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'analytic_distribution', 'analytic_account_msf_private_funds')[1]
70
        except ValueError:
71
            msf_fp_id = 0
1539.26.9 by Olivier DOSSMANN
UF-1894 [ADD] Write journal entries and journal items from migration data
72
        # Browse all wizards
73
        for w in self.browse(cr, uid, ids):
74
            # Search lines
75
            entries = self.pool.get('msf.doc.import.accounting.lines').search(cr, uid, [('wizard_id', '=', w.id)])
76
            if not entries:
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
77
                raise osv.except_osv(_('Error'), _('No lines…'))
1539.26.9 by Olivier DOSSMANN
UF-1894 [ADD] Write journal entries and journal items from migration data
78
            # Browse result
79
            b_entries = self.pool.get('msf.doc.import.accounting.lines').browse(cr, uid, entries)
1638.8.2 by Olivier DOSSMANN
UF-1991 [ADD] New behaviour for Migration entries:
80
            # Update wizard
81
            self.write(cr, uid, [w.id], {'message': _('Grouping by currencies…'), 'progression': 10.0})
1539.26.9 by Olivier DOSSMANN
UF-1894 [ADD] Write journal entries and journal items from migration data
82
            # Search all currencies (to create moves)
1638.8.7 by Olivier DOSSMANN
UF-1991 [FIX] Problem with sad loop for Migration Entries wizard
83
            available_currencies = {}
1539.26.9 by Olivier DOSSMANN
UF-1894 [ADD] Write journal entries and journal items from migration data
84
            for entry in b_entries:
1539.26.10 by Olivier DOSSMANN
UF-1894 [IMP] Import
85
                if (entry.currency_id.id, entry.period_id.id) not in available_currencies:
1638.8.7 by Olivier DOSSMANN
UF-1991 [FIX] Problem with sad loop for Migration Entries wizard
86
                    available_currencies[(entry.currency_id.id, entry.period_id.id)] = []
87
                available_currencies[(entry.currency_id.id, entry.period_id.id)].append(entry)
1638.8.2 by Olivier DOSSMANN
UF-1991 [ADD] New behaviour for Migration entries:
88
            # Update wizard
89
            self.write(cr, uid, ids, {'message': _('Writing a move for each currency…'), 'progression': 20.0})
90
            num = 1
91
            nb_currencies = float(len(available_currencies))
92
            current_percent = 20.0
93
            remaining_percent = 80.0
94
            step = float(remaining_percent / nb_currencies)
1539.26.9 by Olivier DOSSMANN
UF-1894 [ADD] Write journal entries and journal items from migration data
95
            for c_id, p_id in available_currencies:
96
                # Create a move
97
                move_vals = {
98
                    'currency_id': c_id,
1539.26.10 by Olivier DOSSMANN
UF-1894 [IMP] Import
99
                    'manual_currency_id': c_id,
1539.26.9 by Olivier DOSSMANN
UF-1894 [ADD] Write journal entries and journal items from migration data
100
                    'journal_id': journal_id,
101
                    'document_date': w.date,
102
                    'date': w.date,
103
                    'period_id': p_id,
1539.26.10 by Olivier DOSSMANN
UF-1894 [IMP] Import
104
                    'status': 'manu',
1539.26.9 by Olivier DOSSMANN
UF-1894 [ADD] Write journal entries and journal items from migration data
105
                }
106
                move_id = self.pool.get('account.move').create(cr, uid, move_vals, context)
1638.8.7 by Olivier DOSSMANN
UF-1991 [FIX] Problem with sad loop for Migration Entries wizard
107
                for l_num, l in enumerate(available_currencies[(c_id, p_id)]):
1638.8.2 by Olivier DOSSMANN
UF-1991 [ADD] New behaviour for Migration entries:
108
                    # Update wizard
109
                    progression = 20.0 + ((float(l_num) / float(len(b_entries))) * step) + (float(num - 1) * step)
110
                    self.write(cr, uid, [w.id], {'progression': progression})
1638.8.7 by Olivier DOSSMANN
UF-1991 [FIX] Problem with sad loop for Migration Entries wizard
111
                    distrib_id = False
112
                    # Create analytic distribution
1874.4.9 by Olivier DOSSMANN
UTP-944 [ADD] Parce code to find "expense" word in which it needs changes. Do it for:
113
                    if l.account_id.is_analytic_addicted:
1638.8.7 by Olivier DOSSMANN
UF-1991 [FIX] Problem with sad loop for Migration Entries wizard
114
                        distrib_id = self.pool.get('analytic.distribution').create(cr, uid, {}, context)
115
                        common_vals = {
116
                            'distribution_id': distrib_id,
117
                            'currency_id': c_id,
118
                            'percentage': 100.0,
1539.26.9 by Olivier DOSSMANN
UF-1894 [ADD] Write journal entries and journal items from migration data
119
                            'date': l.date,
1638.8.7 by Olivier DOSSMANN
UF-1991 [FIX] Problem with sad loop for Migration Entries wizard
120
                            'source_date': l.date,
121
                            'destination_id': l.destination_id.id,
1539.26.9 by Olivier DOSSMANN
UF-1894 [ADD] Write journal entries and journal items from migration data
122
                        }
1638.8.7 by Olivier DOSSMANN
UF-1991 [FIX] Problem with sad loop for Migration Entries wizard
123
                        common_vals.update({'analytic_id': l.cost_center_id.id,})
124
                        cc_res = self.pool.get('cost.center.distribution.line').create(cr, uid, common_vals)
125
                        common_vals.update({'analytic_id': msf_fp_id, 'cost_center_id': l.cost_center_id.id,})
126
                        fp_res = self.pool.get('funding.pool.distribution.line').create(cr, uid, common_vals)
127
                    # Create move line
128
                    move_line_vals = {
129
                        'move_id': move_id,
130
                        'name': l.description,
131
                        'reference': l.ref,
132
                        'account_id': l.account_id.id,
133
                        'period_id': p_id,
134
                        'document_date': l.document_date,
135
                        'date': l.date,
136
                        'journal_id': journal_id,
137
                        'debit_currency': l.debit,
138
                        'credit_currency': l.credit,
139
                        'currency_id': c_id,
140
                        'analytic_distribution_id': distrib_id,
141
                        'partner_id': l.partner_id and l.partner_id.id or False,
142
                        'employee_id': l.employee_id and l.employee_id.id or False,
143
                    }
144
                    self.pool.get('account.move.line').create(cr, uid, move_line_vals, context, check=False)
1638.8.8 by Olivier DOSSMANN
UF-1991 [FIX] Missing validation for account move after process
145
                # Validate the Journal Entry for lines to be valid (if possible)
1786.7.4 by Olivier DOSSMANN
UTP-766 [IMP] Change Migration wizard behaviour by:
146
                self.write(cr, uid, [w.id], {'message': _('Validating journal entry…')})
1653.4.1 by Olivier DOSSMANN
UF-2045 [FIX] Problem with invalid lines that are not refreshed after being created
147
                self.pool.get('account.move').validate(cr, uid, [move_id], context=context)
1638.8.2 by Olivier DOSSMANN
UF-1991 [ADD] New behaviour for Migration entries:
148
                # Update wizard
149
                progression = 20.0 + (float(num) * step)
150
                self.write(cr, uid, [w.id], {'progression': progression})
151
                num += 1
1638.8.6 by Olivier DOSSMANN
UF-1991 [FIX] Raise error do not return to user. Now migration wizard is updated in order user to be aware
152
        return True
1539.26.9 by Olivier DOSSMANN
UF-1894 [ADD] Write journal entries and journal items from migration data
153
1638.8.2 by Olivier DOSSMANN
UF-1991 [ADD] New behaviour for Migration entries:
154
    def _import(self, dbname, uid, ids, context=None):
1539.26.2 by Olivier DOSSMANN
[WIP] Data migration for accounting lines
155
        """
156
        Do treatment before validation:
157
        - check data from wizard
158
        - check that file exists and that data are inside
159
        - check integrity of data in files
160
        """
161
        # Some checks
162
        if not context:
163
            context = {}
164
        # Prepare some values
1786.7.5 by Olivier DOSSMANN
UTP-766 [WIP] work in progress - YAML tests for Migration wizard
165
        from_yml = False
166
        if context.get('from_yml', False):
167
            from_yml = context.get('from_yml')
168
        # Do changes because of YAML tests
169
        if from_yml:
170
            cr = dbname
171
        else:
172
            cr = pooler.get_db(dbname).cursor()
1539.26.2 by Olivier DOSSMANN
[WIP] Data migration for accounting lines
173
        created = 0
174
        processed = 0
175
        errors = []
176
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
177
        try:
178
            # Update wizard
179
            self.write(cr, uid, ids, {'message': _('Cleaning up old imports…'), 'progression': 1.00})
180
            # Clean up old temporary imported lines
181
            old_lines_ids = self.pool.get('msf.doc.import.accounting.lines').search(cr, uid, [])
182
            self.pool.get('msf.doc.import.accounting.lines').unlink(cr, uid, old_lines_ids)
183
184
            # Check wizard data
185
            for wiz in self.browse(cr, uid, ids):
186
                # Update wizard
187
                self.write(cr, uid, [wiz.id], {'message': _('Checking file…'), 'progression': 2.00})
1687 by jf
UF-1991 [FIX] Finance data migration - Bugs at import
188
                # UF-2045: Check that the given date is in an open period
189
                wiz_period_ids = self.pool.get('account.period').get_period_from_date(cr, uid, wiz.date, context)
190
                if not wiz_period_ids:
191
                    raise osv.except_osv(_('Warning'), _('No period found!'))
192
                period = self.pool.get('account.period').browse(cr, uid, wiz_period_ids[0], context)
193
                if not period or period.state in ['created', 'done']:
194
                    raise osv.except_osv(_('Warning'), _('Period for migration is not open!'))
1786.7.4 by Olivier DOSSMANN
UTP-766 [IMP] Change Migration wizard behaviour by:
195
                date = wiz.date or False
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
196
197
                # Check that a file was given
198
                if not wiz.file:
199
                    raise osv.except_osv(_('Error'), _('Nothing to import.'))
200
                # Update wizard
201
                self.write(cr, uid, [wiz.id], {'message': _('Copying file…'), 'progression': 3.00})
202
                fileobj = NamedTemporaryFile('w+b', delete=False)
203
                fileobj.write(decodestring(wiz.file))
204
                fileobj.close()
205
                content = SpreadsheetXML(xmlfile=fileobj.name)
206
                if not content:
207
                    raise osv.except_osv(_('Warning'), _('No content'))
208
                # Update wizard
209
                self.write(cr, uid, [wiz.id], {'message': _('Processing line…'), 'progression': 4.00})
210
                rows = content.getRows()
211
                nb_rows = len([x for x in content.getRows()])
212
                # Update wizard
213
                self.write(cr, uid, [wiz.id], {'message': _('Reading headers…'), 'progression': 5.00})
214
                # Use the first row to find which column to use
215
                cols = {}
216
                col_names = ['Description', 'Reference', 'Document Date', 'Posting Date', 'G/L Account', 'Third party', 'Destination', 'Cost Centre', 'Booking Debit', 'Booking Credit', 'Booking Currency']
217
                for num, r in enumerate(rows):
218
                    header = [x and x.data for x in r.iter_cells()]
219
                    for el in col_names:
220
                        if el in header:
221
                            cols[el] = header.index(el)
222
                    break
223
                # Number of line to bypass in line's count
224
                base_num = 2
1687 by jf
UF-1991 [FIX] Finance data migration - Bugs at import
225
1539.26.2 by Olivier DOSSMANN
[WIP] Data migration for accounting lines
226
                for el in col_names:
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
227
                    if not el in cols:
1638.8.15 by Olivier DOSSMANN
UF-1991 [FIX] Missing variable
228
                        raise osv.except_osv(_('Error'), _("'%s' column not found in file.") % (el or '',))
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
229
                # All lines
230
                money = {}
1638.8.2 by Olivier DOSSMANN
UF-1991 [ADD] New behaviour for Migration entries:
231
                # Update wizard
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
232
                self.write(cr, uid, [wiz.id], {'message': _('Reading lines…'), 'progression': 6.00})
233
                # Check file's content
234
                for num, r in enumerate(rows):
235
                    # Update wizard
236
                    percent = (float(num+1) / float(nb_rows+1)) * 100.0
237
                    progression = ((float(num+1) * 94) / float(nb_rows)) + 6
238
                    self.write(cr, uid, [wiz.id], {'message': _('Checking file…'), 'progression': progression})
239
                    # Prepare some values
240
                    r_debit = 0
241
                    r_credit = 0
242
                    r_currency = False
243
                    r_partner = False
244
                    r_account = False
245
                    r_destination = False
246
                    r_cc = False
1786.7.13 by Olivier DOSSMANN
UTP-766 [FIX] Do not use document date column in accounting migration import
247
                    # UTP-766: Do not use Document date column, but wizard's one as document date for each line
248
                    #r_document_date = False
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
249
                    current_line_num = num + base_num
250
                    # Fetch all XML row values
251
                    line = self.pool.get('import.cell.data').get_line_values(cr, uid, ids, r)
252
                    # Bypass this line if NO debit AND NO credit
253
                    try:
254
                        bd = line[cols['Booking Debit']]
255
                    except IndexError, e:
256
                        continue
257
                    try:
258
                        bc = line[cols['Booking Credit']]
259
                    except IndexError, e:
260
                        continue
261
                    if not line[cols['Booking Debit']] and not line[cols['Booking Credit']]:
262
                        continue
263
                    processed += 1
264
                    # Check that currency is active
265
                    if not line[cols['Booking Currency']]:
266
                        errors.append(_('Line %s. No currency specified!') % (current_line_num,))
267
                        continue
268
                    curr_ids = self.pool.get('res.currency').search(cr, uid, [('name', '=', line[cols['Booking Currency']])])
269
                    if not curr_ids:
270
                        errors.append(_('Line %s. Currency not found: %s') % (current_line_num, line[cols['Booking Currency']],))
271
                        continue
272
                    for c in self.pool.get('res.currency').browse(cr, uid, curr_ids):
273
                        if not c.active:
274
                            errors.append(_('Line %s. Currency is not active: %s') % (current_line_num, line[cols['Booking Currency']],))
275
                            continue
276
                    r_currency = curr_ids[0]
277
                    if not line[cols['Booking Currency']] in money:
278
                        money[line[cols['Booking Currency']]] = {}
279
                    if not 'debit' in money[line[cols['Booking Currency']]]:
280
                        money[line[cols['Booking Currency']]]['debit'] = 0
281
                    if not 'credit' in money[line[cols['Booking Currency']]]:
282
                        money[line[cols['Booking Currency']]]['credit'] = 0
283
                    if not 'name' in money[line[cols['Booking Currency']]]:
284
                        money[line[cols['Booking Currency']]]['name'] = line[cols['Booking Currency']]
285
                    # Increment global debit/credit
286
                    if line[cols['Booking Debit']]:
287
                        money[line[cols['Booking Currency']]]['debit'] += line[cols['Booking Debit']]
288
                        r_debit = line[cols['Booking Debit']]
289
                    if line[cols['Booking Credit']]:
290
                        money[line[cols['Booking Currency']]]['credit'] += line[cols['Booking Credit']]
291
                        r_credit = line[cols['Booking Credit']]
292
                    # Check document/posting dates
1786.7.13 by Olivier DOSSMANN
UTP-766 [FIX] Do not use document date column in accounting migration import
293
                    # UTP-766: Do not use Document date column, but wizard's one
294
                    #if not line[cols['Document Date']]:
295
                    #    errors.append(_('Line %s. No document date specified!') % (current_line_num,))
296
                    #    continue
1786.7.4 by Olivier DOSSMANN
UTP-766 [IMP] Change Migration wizard behaviour by:
297
                    # UTP-766: Do not use Posting date column, but wizard's one
1786.7.13 by Olivier DOSSMANN
UTP-766 [FIX] Do not use document date column in accounting migration import
298
                    #if line[cols['Document Date']] > date:
299
                    #    errors.append(_("Line %s. Document date '%s' should be inferior or equal to given Posting date '%s'.") % (current_line_num, line[cols['Document Date']], date,))
300
                    #    continue
1786.7.4 by Olivier DOSSMANN
UTP-766 [IMP] Change Migration wizard behaviour by:
301
                    # Fetch document date
1786.7.13 by Olivier DOSSMANN
UTP-766 [FIX] Do not use document date column in accounting migration import
302
                    #r_document_date = line[cols['Document Date']].strftime('%Y-%m-%d')
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
303
                    # Check G/L account
304
                    if not line[cols['G/L Account']]:
305
                        errors.append(_('Line %s. No G/L account specified!') % (current_line_num,))
306
                        continue
307
                    account_ids = self.pool.get('account.account').search(cr, uid, [('code', '=', line[cols['G/L Account']])])
308
                    if not account_ids:
309
                        errors.append(_('Line %s. G/L account %s not found!') % (current_line_num, line[cols['G/L Account']],))
310
                        continue
311
                    r_account = account_ids[0]
312
                    account = self.pool.get('account.account').browse(cr, uid, r_account)
313
                    # Check that Third party exists (if not empty)
314
                    tp_label = _('Partner')
315
                    if line[cols['Third party']]:
316
                        if account.type_for_register == 'advance':
317
                            tp_ids = self.pool.get('hr.employee').search(cr, uid, [('name', '=', line[cols['Third party']])])
318
                            tp_label = _('Employee')
319
                        else:
320
                            tp_ids = self.pool.get('res.partner').search(cr, uid, [('name', '=', line[cols['Third party']])])
321
                        if not tp_ids:
322
                            errors.append(_('Line %s. %s not found: %s') % (current_line_num, tp_label, line[cols['Third party']],))
323
                            continue
324
                        r_partner = tp_ids[0]
1874.4.9 by Olivier DOSSMANN
UTP-944 [ADD] Parce code to find "expense" word in which it needs changes. Do it for:
325
                    # Check analytic axis only if G/L account is analytic-a-holic
326
                    if account.is_analytic_addicted:
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
327
                        # Check Destination
328
                        if not line[cols['Destination']]:
329
                            errors.append(_('Line %s. No destination specified!') % (current_line_num,))
330
                            continue
331
                        destination_ids = self.pool.get('account.analytic.account').search(cr, uid, [('category', '=', 'DEST'), '|', ('name', '=', line[cols['Destination']]), ('code', '=', line[cols['Destination']])])
332
                        if not destination_ids:
333
                            errors.append(_('Line %s. Destination %s not found!') % (current_line_num, line[cols['Destination']],))
334
                            continue
335
                        r_destination = destination_ids[0]
336
                        # Check Cost Center
337
                        if not line[cols['Cost Centre']]:
338
                            errors.append(_('Line %s. No cost center specified!') % (current_line_num,))
339
                            continue
340
                        cc_ids = self.pool.get('account.analytic.account').search(cr, uid, [('category', '=', 'OC'), '|', ('name', '=', line[cols['Cost Centre']]), ('code', '=', line[cols['Cost Centre']])])
341
                        if not cc_ids:
342
                            errors.append(_('Line %s. Cost Center %s not found!') % (current_line_num, line[cols['Cost Centre']]))
343
                            continue
344
                        r_cc = cc_ids[0]
345
                    # NOTE: There is no need to check G/L account, Cost Center and Destination regarding document/posting date because this check is already done at Journal Entries validation.
346
347
                    # Registering data regarding these "keys":
348
                    # - G/L Account
349
                    # - Third Party
350
                    # - Destination
351
                    # - Cost Centre
352
                    # - Booking Currency
353
                    vals = {
354
                        'description': line[cols['Description']] or '',
355
                        'ref': line[cols['Reference']] or '',
356
                        'account_id': r_account or False,
357
                        'debit': r_debit or 0.0,
358
                        'credit': r_credit or 0.0,
359
                        'cost_center_id': r_cc or False,
360
                        'destination_id': r_destination or False,
1786.7.13 by Olivier DOSSMANN
UTP-766 [FIX] Do not use document date column in accounting migration import
361
                        'document_date': date or False, #r_document_date or False,
1786.7.4 by Olivier DOSSMANN
UTP-766 [IMP] Change Migration wizard behaviour by:
362
                        'date': date or False,
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
363
                        'currency_id': r_currency or False,
364
                        'wizard_id': wiz.id,
1786.7.4 by Olivier DOSSMANN
UTP-766 [IMP] Change Migration wizard behaviour by:
365
                        'period_id': period and period.id or False,
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
366
                    }
1539.26.5 by Olivier DOSSMANN
UF-1894 [WIP] work in progress - move third party and employee check for "Third party" column
367
                    if account.type_for_register == 'advance':
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
368
                        vals.update({'employee_id': r_partner,})
1539.26.5 by Olivier DOSSMANN
UF-1894 [WIP] work in progress - move third party and employee check for "Third party" column
369
                    else:
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
370
                        vals.update({'partner_id': r_partner,})
371
                    line_res = self.pool.get('msf.doc.import.accounting.lines').create(cr, uid, vals, context)
372
                    if not line_res:
373
                        errors.append(_('Line %s. A problem occured for line registration. Please contact an Administrator.') % (current_line_num,))
374
                        continue
375
                    created += 1
376
                # Check if all is ok for the file
377
                ## The lines should be balanced for each currency
378
                for c in money:
379
                    if (money[c]['debit'] - money[c]['credit']) >= 10**-2:
380
                        raise osv.except_osv(_('Error'), _('Currency %s is not balanced: %s') % (money[c]['name'], (money[c]['debit'] - money[c]['credit']),))
381
            # Update wizard
382
            self.write(cr, uid, ids, {'message': _('Check complete. Reading potential errors or write needed changes.'), 'progression': 100.0})
383
384
            wiz_state = 'done'
385
            # If errors, cancel probable modifications
386
            if errors:
1638.8.17 by Olivier DOSSMANN
UF-1991 [FIX] Missing rollback methods and update translations
387
                cr.rollback()
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
388
                created = 0
389
                message = _('Import FAILED.')
390
                # Delete old errors
391
                error_ids = self.pool.get('msf.doc.import.accounting.errors').search(cr, uid, [], context)
392
                if error_ids:
393
                    self.pool.get('msf.doc.import.accounting.errors').unlink(cr, uid, error_ids ,context)
394
                # create errors lines
395
                for e in errors:
396
                    self.pool.get('msf.doc.import.accounting.errors').create(cr, uid, {'wizard_id': wiz.id, 'name': e}, context)
397
                wiz_state = 'error'
398
            else:
399
                # Update wizard
400
                self.write(cr, uid, ids, {'message': _('Writing changes…'), 'progression': 0.0})
401
                # Create all journal entries
402
                self.create_entries(cr, uid, ids, context)
403
                message = _('Import successful.')
404
405
            # Update wizard
406
            self.write(cr, uid, ids, {'message': message, 'state': wiz_state, 'progression': 100.0})
407
408
            # Close cursor
1786.7.5 by Olivier DOSSMANN
UTP-766 [WIP] work in progress - YAML tests for Migration wizard
409
            if not from_yml:
1786.7.6 by Olivier DOSSMANN
UTP-766 [FIX] YAML tests on migration wizard
410
                cr.commit()
1786.7.5 by Olivier DOSSMANN
UTP-766 [WIP] work in progress - YAML tests for Migration wizard
411
                cr.close()
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
412
        except osv.except_osv as osv_error:
1638.8.17 by Olivier DOSSMANN
UF-1991 [FIX] Missing rollback methods and update translations
413
            cr.rollback()
1638.8.13 by Olivier DOSSMANN
UF-1991 [FIX] Problem with other raise from def _import in Migration wizard
414
            self.write(cr, uid, ids, {'message': _("An error occured. %s: %s") % (osv_error.name, osv_error.value,), 'state': 'done', 'progression': 100.0})
1786.7.5 by Olivier DOSSMANN
UTP-766 [WIP] work in progress - YAML tests for Migration wizard
415
            if not from_yml:
416
                cr.close()
1638.8.17 by Olivier DOSSMANN
UF-1991 [FIX] Missing rollback methods and update translations
417
        except Exception as e:
418
            cr.rollback()
419
            self.write(cr, uid, ids, {'message': _("An error occured: %s") % (e.args and e.args[0] or '',), 'state': 'done', 'progression': 100.0})
1786.7.5 by Olivier DOSSMANN
UTP-766 [WIP] work in progress - YAML tests for Migration wizard
420
            if not from_yml:
421
                cr.close()
1638.8.2 by Olivier DOSSMANN
UF-1991 [ADD] New behaviour for Migration entries:
422
        return True
423
424
    def button_validate(self, cr, uid, ids, context=None):
425
        """
426
        Launch process in a thread and return a wizard
427
        """
428
        # Some checks
429
        if not context:
430
            context = {}
1786.7.5 by Olivier DOSSMANN
UTP-766 [WIP] work in progress - YAML tests for Migration wizard
431
        if context.get('from_yml', False):
432
            res = self.write(cr, uid, ids, {'state': 'inprogress'}, context=context)
433
            self._import(cr, uid, ids, context=context)
434
        else:
435
            # Launch a thread if we come from web
436
            thread = threading.Thread(target=self._import, args=(cr.dbname, uid, ids, context))
437
            thread.start()
438
            res = self.write(cr, uid, ids, {'state': 'inprogress'}, context=context)
439
        return res
1638.8.2 by Olivier DOSSMANN
UF-1991 [ADD] New behaviour for Migration entries:
440
441
    def button_update(self, cr, uid, ids, context=None):
442
        """
443
        Update view
444
        """
445
        return False
1539.26.2 by Olivier DOSSMANN
[WIP] Data migration for accounting lines
446
447
msf_doc_import_accounting()
1539.26.11 by Olivier DOSSMANN
UF-1894 [FIX] Dependancy problem with next class
448
449
class msf_doc_import_accounting_lines(osv.osv):
450
    _name = 'msf.doc.import.accounting.lines'
451
452
    _columns = {
453
        'description': fields.text("Description", required=False, readonly=True),
454
        'ref': fields.text("Reference", required=False, readonly=True),
455
        'document_date': fields.date("Document date", required=True, readonly=True),
456
        'date': fields.date("Posting date", required=True, readonly=True),
457
        'account_id': fields.many2one('account.account', "G/L Account", required=True, readonly=True),
458
        'destination_id': fields.many2one('account.analytic.account', "Destination", required=False, readonly=True),
459
        'cost_center_id': fields.many2one('account.analytic.account', "Cost Center", required=False, readonly=True),
460
        'debit': fields.float("Debit", required=False, readonly=True),
461
        'credit': fields.float("Credit", required=False, readonly=True),
462
        'currency_id': fields.many2one('res.currency', "Currency", required=True, readonly=True),
463
        'partner_id': fields.many2one('res.partner', "Partner", required=False, readonly=True),
464
        'employee_id': fields.many2one('hr.employee', "Employee", required=False, readonly=True),
465
        'period_id': fields.many2one('account.period', "Period", required=True, readonly=True),
1539.26.12 by Olivier DOSSMANN
UF-1894 [FIX] Error on wizard_id field for imported lines
466
        'wizard_id': fields.integer("Wizard", required=True, readonly=True),
1539.26.11 by Olivier DOSSMANN
UF-1894 [FIX] Dependancy problem with next class
467
    }
468
469
    _defaults = {
470
        'description': lambda *a: '',
471
        'ref': lambda *a: '',
472
        'document_date': lambda *a: strftime('%Y-%m-%d'),
473
        'date': lambda *a: strftime('%Y-%m-%d'),
474
        'debit': lambda *a: 0.0,
475
        'credit': lambda *a: 0.0,
476
    }
477
478
msf_doc_import_accounting_lines()
1638.8.2 by Olivier DOSSMANN
UF-1991 [ADD] New behaviour for Migration entries:
479
480
class msf_doc_import_accounting_errors(osv.osv_memory):
481
    _name = 'msf.doc.import.accounting.errors'
482
483
    _columns = {
1638.8.4 by Olivier DOSSMANN
UF-1991 [FIX] Problem with wizard on "msg" field. Change it to "name".
484
        'name': fields.text("Description", readonly=True, required=True),
1638.8.2 by Olivier DOSSMANN
UF-1991 [ADD] New behaviour for Migration entries:
485
        'wizard_id': fields.many2one('msf.doc.import.accounting', "Wizard", required=True, readonly=True),
486
    }
487
488
msf_doc_import_accounting_errors()
1539.26.2 by Olivier DOSSMANN
[WIP] Data migration for accounting lines
489
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: