~jfb-tempo-consulting/unifield-wm/sync-env-py3

« back to all changes in this revision

Viewing changes to mkdb.py

  • Committer: Samus CTO
  • Date: 2012-08-28 12:38:31 UTC
  • Revision ID: cto@openerp.com-20120828123831-9dhavvjktnrl2p8d
[INIT]

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
# -*- coding: utf-8 -*-
3
 
"""
4
 
  (C) 2012 OpenERP - All rights reserved
5
 
 
6
 
"""
 
1
#!/usr/bin/env python2
7
2
 
8
3
#Load config file
9
4
import config
10
 
from config import coordo_count, project_count, hq_count, default_oc
11
 
 
12
 
import sys
13
 
import os
14
 
import shutil
15
 
import time
16
 
import uuid
17
 
import re
18
 
 
19
 
import argparse
20
 
from subprocess import call
21
 
 
22
 
import base64
23
 
import csv
24
 
from passlib.hash import bcrypt
25
 
 
26
 
assert hq_count > 0, "You must have at least one HQ!"
27
 
 
28
 
from scripts.common import client, db_instance, Synchro, check_lp_update, get_revno_from_path
29
 
 
30
 
if sys.version_info >= (2, 7):
31
 
    import unittest
32
 
else:
33
 
    # Needed for setUpClass and skipIf methods
34
 
    import unittest27 as unittest
35
 
 
36
 
from datetime import datetime
37
 
from dateutil.relativedelta import relativedelta
38
 
 
39
 
 
40
 
bool_configuration_only = False
41
 
bool_creation_only = False
42
 
master_dir = '/'.join(os.path.realpath(__file__).split('/')[0:-1]+['master_dump'])
43
 
master_prefix_name = 'msf_profile_sync_so'
44
 
dir_to_dump = os.path.join(config.dump_dir, time.strftime('%Y%m%d%H%M'))
45
 
 
46
 
def get_file_from_source(filename):
47
 
    if filename:
48
 
        last = filename.split('/')[-1]
49
 
        newfile = os.path.expanduser('~/unifield-server/bin/addons/msf_profile/user_rights/%s' % last)
50
 
        if os.path.exists(newfile):
51
 
            return newfile
52
 
    return filename
53
 
 
54
 
def get_oc(dbname):
55
 
    if isinstance(default_oc, dict):
56
 
        hq_name = re.findall(r'HQ[0-9]+', dbname)
57
 
        if hq_name:
58
 
            return default_oc.get(hq_name[-1], 'oca')
59
 
        return 'oca'
60
 
    return default_oc
61
 
 
62
 
def warn(*messages):
63
 
    sys.stderr.write(" ".join(messages)+"\n")
64
 
 
65
 
# Fake TestCase to enable/disable quickly some tests
66
 
class creation_only(unittest.TestCase):
67
 
    pass
68
 
 
69
 
class configuration_only(unittest.TestCase):
70
 
    pass
71
 
 
72
 
class skip_all(unittest.TestCase):
73
 
    pass
74
 
 
75
 
def get_users_from_file(filename):
76
 
 
77
 
    LOGIN_COLUMN_INDEX=1
78
 
    PASSWD_COLUMN_INDEX=2
79
 
    FOR_HQ_COLUMN_INDEX=3
80
 
    FOR_COORDO_COLUMN_INDEX=4
81
 
    FOR_PROJECT_COLUMN_INDEX=5
82
 
 
83
 
    FIRST_GROUP_COLUMN_INDEX=6
84
 
 
85
 
    SELECTION_CHAR='X'
86
 
 
87
 
    users = []
88
 
    with open(filename, 'r') as csvfile:
89
 
        reader = csv.reader(csvfile, delimiter=';')
90
 
        header=False
91
 
 
92
 
        groups = []
93
 
 
94
 
        for row in reader:
95
 
            if not header:
96
 
                header=True
97
 
 
98
 
                for index in range(FIRST_GROUP_COLUMN_INDEX, len(row)):
99
 
                    groups.append((index, row[index]))
100
 
            else:
101
 
                user_groups = []
102
 
                for grp in groups:
103
 
                    if row[grp[0]] == SELECTION_CHAR:
104
 
                        user_groups.append(grp[1])
105
 
 
106
 
                data = {
107
 
                    'login': row[LOGIN_COLUMN_INDEX],
108
 
                    'passwd': row[PASSWD_COLUMN_INDEX],
109
 
                    'for_hq': True if row[FOR_HQ_COLUMN_INDEX] == SELECTION_CHAR else False,
110
 
                    'for_co': True if row[FOR_COORDO_COLUMN_INDEX] == SELECTION_CHAR else False,
111
 
                    'for_pr': True if row[FOR_PROJECT_COLUMN_INDEX] == SELECTION_CHAR else False,
112
 
                    'groups': user_groups
113
 
                }
114
 
 
115
 
                users.append(data)
116
 
    return users
117
 
 
118
 
 
119
 
# Determin skip flags if needed
120
 
skipDrop = True
121
 
skipDumpDbs = False
122
 
skipBranchesUpdate = True
123
 
 
124
 
if __name__ == '__main__':
125
 
    parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
126
 
    parser.add_argument("--nodrop", "-n", action='store_true', default=False, help="Don't drop existing db")
127
 
    parser.add_argument("--nodump", action='store_true', default=False, help="Disable dbs dump at the end")
128
 
    parser.add_argument("--log-to-file", action='store_true', default=False, help="Log the unittest")
129
 
    parser.add_argument("--update-code", action='store_true', default=False, help="Update the code, restart servers and create db if needed")
130
 
    parser.add_argument('unit_test_option', nargs='*', help='Tests to start: server_creation hq01_creation coordo01_creation dump_all  ...')
131
 
 
132
 
 
133
 
    o = parser.parse_args()
134
 
    if o.nodump and 'dump_all' not in o.unit_test_option:
135
 
        skipDumpDbs = True
136
 
    elif o.unit_test_option and 'dump_all' not in o.unit_test_option:
137
 
        o.unit_test_option.append('dump_all')
138
 
 
139
 
    if o.update_code or 'update_branches' in  o.unit_test_option:
140
 
        skipBranchesUpdate = False
141
 
        if o.unit_test_option and 'update_branches' not in o.unit_test_option:
142
 
            o.unit_test_option.insert(0, 'update_branches')
143
 
 
144
 
    sys.argv = [sys.argv[0]] + o.unit_test_option
145
 
    skipDrop = o.nodrop
146
 
 
147
 
    bool_creation_only = bool('creation_only' in sys.argv) or bool('skip_all' in sys.argv)
148
 
    bool_configuration_only = bool('configuration_only' in sys.argv) or bool('skip_all' in sys.argv)
149
 
else:
150
 
    bool_skip_all = bool(__name__+'.skip_all' in sys.argv)
151
 
    if bool_skip_all:
152
 
        bool_creation_only = True
153
 
        bool_configuration_only = True
154
 
    else:
155
 
        bool_creation_only = bool(__name__+'.creation_only' in sys.argv)
156
 
        bool_configuration_only = bool(__name__+'.configuration_only' in sys.argv)
157
 
 
158
 
skipCreation = bool_configuration_only
159
 
skipModules = bool_configuration_only
160
 
skipSyncSo = bool_configuration_only
161
 
skipModuleUpdate = bool_configuration_only
162
 
skipUniUser = bool_configuration_only
163
 
skipMasterCreation = False
164
 
skipGroups = bool_creation_only
165
 
skipPropInstance = bool_creation_only
166
 
skipConfig = bool_creation_only
167
 
skipRegister = bool_creation_only
168
 
skipSync = bool_creation_only
169
 
skipSync = bool_creation_only
170
 
skipModuleData = bool_creation_only
171
 
skipPartner = bool_creation_only
172
 
skipManualConfig = bool_creation_only
173
 
skipOpenPeriod = bool_creation_only
174
 
skipLoadUACFile = bool_creation_only
175
 
skipCreateUsers = bool_creation_only
176
 
skipLoadExtraFiles = bool_creation_only
177
 
 
178
 
# eval cond during the run
179
 
def skip_test_real_eval(cond, reason):
180
 
    def deco(fun):
181
 
        def wrap(*a, **b):
182
 
            if eval(cond):
183
 
                raise unittest.SkipTest(reason)
184
 
            return fun(*a, **b)
185
 
        return wrap
186
 
    return deco
187
 
 
188
 
class update_branches(unittest.TestCase):
189
 
 
190
 
    @unittest.skipIf(skipBranchesUpdate, "Branches update deactivated")
191
 
    def test_01_update_branch(self):
192
 
        to_up = check_lp_update(True)
193
 
        if 'unifield-web' in to_up:
194
 
            if not config.web_restart_cmd:
195
 
                raise self.fail('web_restart_cmd not define in config.py')
196
 
            call(config.web_restart_cmd, shell=True)
197
 
            to_up.remove('unifield-web')
198
 
        if to_up:
199
 
            if not config.server_restart_cmd:
200
 
                raise self.fail('server_restart_cmd not define in config.py')
201
 
            call(config.server_restart_cmd, shell=True)
202
 
            time.sleep(5)
203
 
        if not to_up:
204
 
            raise self.fail('No new code to pull')
205
 
 
206
 
 
207
 
# Base of database creation
 
5
 
 
6
#Load OpenERP Client Library
 
7
import openerplib
 
8
 
 
9
#Load tests procedures
 
10
import unittest
 
11
#from tests import *
 
12
from tests.openerplib import db
 
13
 
 
14
from scripts.common import Synchro, HQ, Coordo, Project, Project2
 
15
 
 
16
try:
 
17
    import ipdb as pdb
 
18
except:
 
19
    import pdb
 
20
 
 
21
skipCreation = False
 
22
skipModules = False
 
23
skipConfig = False
 
24
skipGroups = False
 
25
skipModuleTest = False
 
26
skipRegister = False
 
27
skipSync = False
 
28
skipUniUser = False
 
29
 
208
30
class db_creation(object):
209
31
 
210
 
    #ignore_wizard = ['sale.price.setup'] # Fixed in unifield-wm > SP5
211
 
    ignore_wizard = ['msf_button_access_rights.view_config_wizard_install']
 
32
    buggy_models = ('sale.price.setup',)
212
33
 
213
34
    base_wizards = {
214
 
        'base.setup.config' : {
215
 
            'button' : 'config',
216
 
        },
217
35
        'res.config.view' : {
218
36
            'name' : "auto_init",
219
37
            'view' : 'extended',
221
39
        'sale.price.setup' : {
222
40
            'sale_price' : 0.10,
223
41
        },
 
42
        'msf_instance.setup' : {
 
43
            'button' : 'action_skip',
 
44
        },
 
45
        'account.installer' : {
 
46
            'charts' : 'msf_chart_of_account',
 
47
        },
224
48
        'stock.location.configuration.wizard' : {
225
49
            'location_type' : 'internal',
226
50
            'location_usage' : 'stock',
227
51
            'location_name' : 'Test Location',
228
52
            'button' : 'action_stop',
229
53
        },
230
 
        'currency.setup' : {
231
 
            'functional_id' : config.default_currency,
232
 
        },
233
 
        'base.setup.company': {
234
 
            'contact_name': 'msf',
235
 
        }
236
54
    }
237
55
 
238
56
    db = None
239
 
    parent = None
240
 
 
241
 
    @property
242
 
    def parent_name(self):
243
 
        return self.parent.db.name if self.parent else None
244
 
 
245
 
    @classmethod
246
 
    def getNameFormat(cls):
247
 
        return  {
248
 
            'db': config.prefix,
249
 
            'ind': cls.index,
250
 
            'pind': cls.parent and cls.parent.index or '','ppind': cls.parent and cls.parent.parent and cls.parent.parent.index or ''
251
 
        }
252
 
 
253
 
    @classmethod
254
 
    def setUpClass(cls):
255
 
        if cls.db is None and hasattr(cls, 'index'):
256
 
            if cls.parent is not None:
257
 
                cls.parent.setUpClass()
258
 
 
259
 
 
260
 
            name = cls.name_format % cls.getNameFormat()
261
 
            if hasattr(config, 'sync_user_admin') and config.sync_user_admin:
262
 
                sync_user = 'admin'
263
 
            else:
264
 
                sync_user = name
265
 
 
266
 
            cls.db = db_instance(
267
 
                server=client,
268
 
                name=name,
269
 
                synchro={
270
 
                    'protocol' : 'xmlrpc',
271
 
                    'host' : config.server_host,
272
 
                    'port' : config.server_port,
273
 
                    'database' : Synchro.name,
274
 
                    'login' : sync_user,
275
 
                    'password' : config.admin_password,
276
 
                    'timeout': 600,
277
 
                    'netrpc_retry': 10,
278
 
                    'xmlrpc_retry': 10,
279
 
                },
280
 
            )
281
 
            last_sync.test_cases.append(cls)
282
57
 
283
58
    def setUp(self):
284
59
        if self.db is None:
285
 
            self.fail("Bad use of class")
 
60
            raise Exception("Bad use of class")
286
61
 
287
 
    @unittest.skipIf(skipDrop, "Drop DB deactivated")
 
62
    @unittest.skipIf(skipCreation, "Creation desactivated")
288
63
    def test_00_drop(self):
289
64
        self.db.connect('admin')
290
65
        self.db.drop()
291
66
 
292
 
    @skip_test_real_eval("skipCreation", "Creation desactivated")
 
67
    @unittest.skipIf(skipCreation, "Creation desactivated")
293
68
    def test_01_create_db(self):
294
69
        self.db.connect('admin')
295
70
        self.db.create_db(config.admin_password)
296
71
        self.db.wait()
297
 
        self.db.user('admin').addGroups('Useability / Extended View')
298
72
 
299
 
    @skip_test_real_eval("skipModules", "Modules installation desactivated")
 
73
    @unittest.skipIf(skipModules, "Modules installation desactivated")
300
74
    def test_02_base_install(self):
301
75
        self.db.connect('admin')
302
76
        self.db.module('msf_profile').install().do()
303
 
 
304
 
 
305
 
    @skip_test_real_eval("skipSyncSo", "Modules installation desactivated")
306
 
    def test_04_sync_so_install(self):
307
 
        self.db.connect('admin')
308
77
        self.db.module('sync_so').install().do()
309
 
        # disable automatic backup
310
 
        backup_ids = self.db.get('ir.model').search([('model', '=', 'backup.config')])
311
 
        if backup_ids:
312
 
            self.db.get('backup.config').write([1], {
313
 
                'beforemanualsync': False,
314
 
                'beforeautomaticsync': False,
315
 
                'aftermanualsync': False,
316
 
                'afterautomaticsync': False,
317
 
                'scheduledbackup': False
318
 
            })
319
 
 
320
 
    @skip_test_real_eval("skipUniUser", "UniField user creation desactivated")
321
 
    def test_05_unifield_user_creation(self):
322
 
        self.db.connect('admin')
323
 
        if not hasattr(config, 'load_uac_file') or not config.load_uac_file:
324
 
            self.db.user('unifield').add('admin').addGroups('Sync / User', 'Purchase / User')
325
 
 
 
78
 
 
79
    @unittest.skipIf(skipModules, "Modules installation desactivated")
 
80
    def test_03_specific_install(self):
 
81
        self.db.connect('admin')
 
82
        if self.db is Synchro:
 
83
            self.db.module('sync_server_test').install().do()
 
84
            self.db.module('update_server').install().do()
 
85
        else:
 
86
            self.db.module('update_client').install()
 
87
            self.db.module('sync_client_web').install().do()
 
88
            Synchro.connect('admin')
 
89
            Synchro.user(self.db.__name__).add(self.db.__name__).addGroups('Sync / User')
 
90
            # Force reconnect to set connection manager
 
91
            self.db.connect('admin', reconnect=True)
 
92
 
 
93
    @unittest.skipIf(skipUniUser, "Unifield user creation desactivated")
 
94
    def test_04_unifield_user_creation(self):
 
95
        self.db.connect('admin')
 
96
        self.db.user('unifield').add('admin').addGroups('Sync / User', 'Purchase / User')
326
97
 
327
98
    def configure(self):
328
 
        # We did rather start on msf_instance.setup...
329
 
        # Reason: For an unknown reason, this wizard is set as 'done' automatically after run any first wizard
330
 
        #model = 'base.setup.installer'
331
 
        model = 'msf_instance.setup'
 
99
        model = 'base.setup.installer'
332
100
        while model != 'ir.ui.menu':
333
101
            try:
334
 
                # skip account.installer if no parent_name providen (typically: HQ instance)
335
 
                if model in self.ignore_wizard or \
336
 
                   (model == 'account.installer' and self.parent_name is not None) or \
337
 
                   (model == 'msf_instance.setup' and self.db is Synchro):
 
102
                if model in self.buggy_models or (model == 'account.installer' and self.db not in (Synchro, HQ)):
338
103
                    proxy = self.db.get(model)
339
104
                    answer = proxy.action_skip([])
340
 
                elif model == 'msf_instance.setup':
341
 
                    instance_id = self.db.search_data('msf.instance', [('instance','=',self.db.name)])[0]
342
 
                    self.db.get('res.company').write([1], {'instance_id': instance_id})
343
 
                    answer = self.db.wizard(model, {'instance_id': instance_id}).action_next()
 
105
                elif model == 'base.setup.config':
 
106
                    answer = self.db.wizard(model, data).config()
344
107
                else:
345
 
                    data = dict(self.base_wizards.get(model, {}))
346
 
                    if model == 'currency.setup':
347
 
                        hq_name = self.db and self.db.name and re.findall(r'HQ[0-9]+', self.db.name)
348
 
                        if hq_name and hasattr(config, 'currency_tree'):
349
 
                            data['functional_id'] = config.currency_tree.get(hq_name[-1], config.default_currency)
350
 
                    if model == 'fixed.asset.setup':
351
 
                        data['fixed_asset_ok'] = True
 
108
                    data = self.base_wizards.get(model, {})
352
109
                    button = data.pop('button', 'action_next')
353
110
                    answer = getattr(self.db.wizard(model, data), button)()
354
111
                model = answer.get('res_model', None)
355
112
            except:
356
 
                warn("DEBUG: db=%s, model=%s" % (self.db.name, model))
 
113
                print "DEBUG: db=%s, model=%s" % (self.db.__name__, model)
357
114
                raise
358
115
 
359
 
    @classmethod
360
 
    def sync(cls, db=None):
361
 
        if db is None: db = cls.db
362
 
        db.connect('admin')
363
 
        db.get('sync.client.sync_server_connection').connect()
 
116
    def sync(self, db=None):
 
117
        if db is None: db = self.db
364
118
        if not db.get('sync.client.entity').sync():
365
119
            monitor = db.get('sync.monitor')
366
120
            ids = monitor.search([], 0, 1, '"end" desc')
367
 
            raise Exception('Synchronization process of database "%s" failed!\n%s' % (db.db_name,monitor.read(ids, ['error'])[0]['error']))
368
 
 
369
 
    # Create Cost Center and Proprietary Instance for Test Cases
370
 
    def make_prop_instance(self, hq, prop_instance=None, mission=None):
371
 
        hq.connect('admin')
372
 
        # Get 2 cost centers: the top one and the normal one
373
 
        cost_center_id = False
374
 
        top_cost_center_id = False
375
 
        mission_suffix = 'OC'
376
 
        month_12 = (datetime.now() + relativedelta(day=1, months=-12)).strftime('%Y-%m-%d')
377
 
        if mission and mission.db is hq:
378
 
            # coordo
379
 
            mission_suffix = "%02d" % self.index
380
 
            top_data = {
381
 
                'name' : "HT%d" % (self.index),
382
 
                'code' : "HT%d" % (self.index),
383
 
                'category' : 'OC',
384
 
                'type' : 'view',
385
 
                'parent_id' : hq.search_data('account.analytic.account', {'Code':'OC'})[0],
386
 
                'date_start': month_12,
387
 
            }
388
 
            top_cost_center_id = hq.get('account.analytic.account').create(top_data)
389
 
            data = {
390
 
                'name' : "HT%d01" % (self.index),
391
 
                'code' : "HT%d01" % (self.index),
392
 
                'category' : 'OC',
393
 
                'type' : 'normal',
394
 
                'parent_id' : top_cost_center_id,
395
 
                'date_start': month_12,
396
 
            }
397
 
            cost_center_id = hq.get('account.analytic.account').create(data)
398
 
        elif self.db is not hq:
399
 
            # project
400
 
            mission_suffix = "%02d" % mission.index
401
 
            parent_cost_center_id = hq.search_data('account.analytic.account', {'Code':"HT%d" % (mission.index)})[0]
402
 
            data = {
403
 
                'name' : "HT%d%d1" % (mission.index, self.index),
404
 
                'code' : "HT%d%d1" % (mission.index, self.index),
405
 
                'category' : 'OC',
406
 
                'type' : 'normal',
407
 
                'parent_id' : parent_cost_center_id,
408
 
                'date_start': month_12,
409
 
            }
410
 
            top_cost_center_id = hq.get('account.analytic.account').create(data)
411
 
        data = {
412
 
            'code' : self.db.name,
413
 
            'name' : self.db.name,
414
 
            'instance' : self.db.name,
415
 
            'mission' : '%s_MISSION_%s' % (config.prefix, mission_suffix),
416
 
        }
417
 
        if prop_instance is not None:
418
 
            data.update(prop_instance)
419
 
        if not hq.test('msf.instance', data):
420
 
            instance_id = hq.get('msf.instance').create(data)
421
 
            if self.db is not hq:
422
 
                # Create/update cost center lines as needed by level
423
 
                if mission.db is hq:
424
 
                    # Coordo: add cost center lines to the instance, tick both
425
 
                    top_line_data = {
426
 
                        'instance_id' : instance_id,
427
 
                        'cost_center_id' : top_cost_center_id,
428
 
                        'is_target' : True,
429
 
                        'is_top_cost_center' : True,
430
 
                        'is_po_fo_cost_center' : False,
431
 
                    }
432
 
                    hq.get('account.target.costcenter').create(top_line_data)
433
 
                    line_data = {
434
 
                        'instance_id' : instance_id,
435
 
                        'cost_center_id' : cost_center_id,
436
 
                        'is_target' : True,
437
 
                        'is_top_cost_center' : False,
438
 
                        'is_po_fo_cost_center' : True,
439
 
                    }
440
 
                    hq.get('account.target.costcenter').create(line_data)
441
 
                else:
442
 
                    # Project: add cost center lines to parent coordo instance, tick them in instance
443
 
                    top_line_data = {
444
 
                        'instance_id' : data['parent_id'],
445
 
                        'cost_center_id' : top_cost_center_id,
446
 
                        'is_target' : False,
447
 
                        'is_top_cost_center' : False,
448
 
                        'is_po_fo_cost_center' : False,
449
 
                    }
450
 
                    hq.get('account.target.costcenter').create(top_line_data)
451
 
                    project_target_ids = hq.search_data('account.target.costcenter', {'instance_id' : instance_id, 'cost_center_id' : top_cost_center_id})
452
 
                    hq.write('account.target.costcenter', project_target_ids, {'is_target': True, 'is_top_cost_center': True, 'is_po_fo_cost_center' : True})
453
 
                self.sync(hq)
454
 
 
455
 
    def add_to_group(self, group_name, group_type):
456
 
        Synchro.connect('admin')
457
 
        oc = get_oc(self.db.name)
458
 
        entity_ids = Synchro.get('sync.server.entity').search([('name','=',self.db.name)])
459
 
        assert len(entity_ids) == 1, "The entity must exists!"
460
 
        # Make groups
461
 
        group = Synchro.get('sync.server.entity_group')
462
 
        # Make or update OC group
463
 
        group_ids = group.search([('name','=',group_name)])
464
 
        if group_ids:
465
 
            group.write(group_ids, {'entity_ids' : [(4,entity_ids[0])]})
466
 
        else:
467
 
            Type = Synchro.get('sync.server.group_type')
468
 
            type_ids = Type.search([('name', '=', group_type)])
469
 
            if not type_ids:
470
 
                type_ids = [Type.create({'name':group_type})]
471
 
            group.create({
472
 
                'name' : group_name,
473
 
                'type_id' : type_ids[0],
474
 
                'entity_ids' : [(6,0,entity_ids)],
475
 
                'oc': oc
476
 
            })
477
 
 
478
 
    @classmethod
479
 
    def dump_db(self, path, name=None):
480
 
        if self.db is None:
481
 
            self.setUpClass()
482
 
        if not os.path.exists(path):
483
 
            os.makedirs(path)
484
 
        if name is None:
485
 
            self.db.connect()
486
 
            name =self.db.db_name
487
 
        bckfile = os.path.join(path, '%s.dump' % name)
488
 
        orig_bck = bckfile
489
 
        i = 0
490
 
        while os.path.exists(bckfile):
491
 
            i += 1
492
 
            bckfile = os.path.join(path, '%s_%s.dump' % (name, i))
493
 
        if i:
494
 
            shutil.move(orig_bck, bckfile)
495
 
        self.db.dump_db_file(orig_bck)
496
 
 
497
 
    def restore_db(self):
498
 
        dump = os.path.join(master_dir, "%s.dump" % (master_prefix_name,) ) #self.db.name)
499
 
        self.db.connect('admin')
500
 
        self.db.restore_db_file(self.db.name, dump)
501
 
        # wait process
502
 
        time.sleep(10)
503
 
 
504
 
# Run a last sync after all synchronization
505
 
class last_sync(unittest.TestCase):
506
 
    test_cases = []
507
 
 
508
 
    def test_50_last_synchronization(self):
509
 
        if not self.test_cases:
510
 
            self.skipTest("No database to update")
511
 
        for i in [0,1]:
512
 
            for tc in self.test_cases:
513
 
                assert issubclass(tc, db_creation), "The object %s is not of type db_creation!"
514
 
                tc.sync()
515
 
 
516
 
class activate_inter_partner(unittest.TestCase):
517
 
 
518
 
    def test_99_activate_inter_partner(self):
519
 
        all_projects = []
520
 
        for tc in test_cases:
521
 
            if issubclass(tc, projectn_creation):
522
 
                all_projects.append(tc.db.name)
523
 
        for tc in test_cases:
524
 
            if issubclass(tc, (coordon_creation, projectn_creation)):
525
 
                db = tc.db
526
 
                db.connect('admin')
527
 
                p_obj = db.get('res.partner')
528
 
                exclude_name = [db.name]
529
 
                same_mission_ids = p_obj.search([('partner_type', '=', 'internal')])
530
 
                for p in p_obj.read(same_mission_ids, ['name']):
531
 
                    exclude_name.append(p['name'])
532
 
                exclude_name += all_projects
533
 
                partner_ids = p_obj.search([('partner_type', 'in', ['section', 'intermission']), ('active', '=', False), ('name', 'not in', exclude_name)])
534
 
                if partner_ids:
535
 
                    p_obj.write(partner_ids, {'active': True})
536
 
                ext_ids = p_obj.search([('partner_type', '=', 'external'), ('active', '=', False)])
537
 
                if ext_ids:
538
 
                    p_obj.write(ext_ids, {'active': True})
539
 
 
540
 
class dump_all(unittest.TestCase):
541
 
 
542
 
    @unittest.skipIf(skipDumpDbs, "DBs dump directory creation deactivated")
543
 
    def test_00_create_dump_dir(self):
544
 
        if not os.path.exists(dir_to_dump):
545
 
            os.makedirs(dir_to_dump)
546
 
 
547
 
    @unittest.skipIf(skipDumpDbs, "DBs dump deactivated")
548
 
    def test_10_dump_all(self):
549
 
        for tc in test_cases:
550
 
            if issubclass(tc, db_creation):
551
 
                tc.dump_db(dir_to_dump)
552
 
 
553
 
    @unittest.skipIf(skipDumpDbs, "DBs dump deactivated")
554
 
    def test_20_dump_branch_info(self):
555
 
        info = {}
556
 
        for ad in config.addons:
557
 
            src_path = os.path.join(config.source_path, ad)
558
 
            if not os.path.exists(src_path):
559
 
                raise self.fail('%s does not exist ! Did you set source_path in config.py ?' % src_path)
560
 
            info[ad] = get_revno_from_path(src_path)
561
 
        f = open(os.path.join(dir_to_dump, 'info.txt'), 'w')
562
 
        for mod, data in list(info.items()):
563
 
            f.write("%s_url=%s\n" % (mod, data['lpurl']))
564
 
            f.write("%s_revno=%s\n" % (mod, data['revno']))
565
 
        f.close()
566
 
 
567
 
 
568
 
# Specific Sync Server creation
569
 
class server_creation(db_creation, unittest.TestCase):
 
121
            self.fail('Synchronization process of database "%s" failed!\n%s' % (db.db_name,monitor.read(ids, ['error'])[0]['error']))
 
122
 
 
123
class synchro_creation(db_creation, unittest.TestCase):
570
124
    db = Synchro
571
125
 
572
 
    def test_02_install_lang(self):
573
 
        self.db.connect('admin')
574
 
        lang = False
575
 
        if hasattr(config, 'lang'):
576
 
            lang = config.lang
577
 
        if lang:
578
 
            #if self.db.get('sync.client.entity'):
579
 
            #    call(config.server_restart_cmd, shell=True)
580
 
            #    time.sleep(5)
581
 
            lang_obj = self.db.get('res.lang')
582
 
            lang_id = lang_obj.search([('code', '=', lang)])
583
 
            mod_obj = self.db.get('ir.module.module')
584
 
            if lang_id:
585
 
                lang_obj.write(lang_id, {'translatable': True})
586
 
                mod_ids = mod_obj.search([('state', '=', 'installed')])
587
 
                mod_obj.button_update_translations(mod_ids, lang)
588
 
 
589
 
    @unittest.skipIf(skipMasterCreation, "Master dump creation desactivated")
590
 
    def test_03_dump_master(self):
591
 
        self.dump_db(master_dir, master_prefix_name)
592
 
 
593
 
    @unittest.skipIf(skipModuleUpdate, "update_server installation desactivated")
594
 
    def test_10_install_update_server(self):
595
 
        self.db.connect('admin')
596
 
        self.db.module('update_server').install().do()
597
 
        self.db.module('update_client').install().do()
598
 
 
599
 
    @unittest.skipIf(skipModuleData, "Data module installation desactivated")
600
 
    def test_10_install_data_server(self):
601
 
        self.db.connect('admin')
602
 
        self.db.module('sync_remote_warehouse_server').install().do()
603
 
        self.db.module('msf_sync_data_server').install().do()
 
126
    @unittest.skipIf(skipGroups, "Group creation desactivated")
 
127
    def test_10_make_groups(self):
 
128
        group = Synchro.get('sync.server.entity_group')
 
129
        group.unlink(group.search([]))
 
130
        group_type = Synchro.get('sync.server.group_type')
 
131
        group.create({
 
132
            'name' : 'Section',
 
133
            'type_id' : group_type.search([('name','=','Section')])[0],
 
134
        })
 
135
        group.create({
 
136
            'name' : 'Mission',
 
137
            'type_id' : group_type.search([('name','=','Coordination')])[0],
 
138
        })
604
139
 
605
140
    @unittest.skipIf(skipConfig, "Modules configuration desactivated")
606
 
    def test_30_configuration_wizards(self):
 
141
    def test_20_configuration_wizards(self):
607
142
        self.db.connect('admin')
608
143
        self.configure()
609
144
 
610
145
    @unittest.skipIf(skipSync, "Synchronization desactivated")
611
 
    def test_40_activate_rules(self):
612
 
        self.db.connect('admin')
613
 
        sync_rule_obj = Synchro.get('sync_server.message_rule')
614
 
        rule_ids = sync_rule_obj.search([('active', '=', 1)])
615
 
        for rule in sync_rule_obj.read(rule_ids, ['model_id']):
616
 
            sync_rule_obj.write(rule['id'], {'model_id': rule['model_id'] , 'status': 'valid'})
617
 
        #Synchro.activate('sync_server.sync_rule', [])
618
 
 
619
 
    def test_99_add_shortcut(self):
620
 
        self.db.connect('admin')
621
 
        menu_to_add = ['sync_server.entity_menu', 'sync_server.sync_rule_menu', 'sync_server.message_rule_menu']
622
 
        for menu in menu_to_add:
623
 
            module, xml = menu.split('.')
624
 
            menu_id = self.db.get('ir.model.data').get_object_reference(module, xml)[1]
625
 
            menu_name = self.db.get('ir.ui.menu').name_get([menu_id])[0][1]
626
 
            try:
627
 
                self.db.get('ir.ui.view_sc').create({'res_id': menu_id, 'name': menu_name})
628
 
            except:
629
 
                raise
630
 
 
631
 
# Base for instances creation ('is not Synchro')
 
146
    def test_30_activate_rules(self):
 
147
        self.db.connect('admin')
 
148
        Synchro.activate('sync_server.sync_rule', [])
 
149
 
632
150
class client_creation(db_creation):
633
 
    def import_csv(self, filename):
634
 
        model = os.path.splitext(os.path.basename(filename))[0]
635
 
        if model in ('product.nomenclature', 'product.category', 'product.product'):
636
 
            req = self.db.get('res.request')
637
 
            nb = req.search([])
638
 
            wiz = self.db.get('import_data')
639
 
            f = open(filename, 'rb')
640
 
            rec_id = wiz.create({'object': model, 'file': base64.b64encode(f.read()).decode('utf8')})
641
 
            f.close()
642
 
            wiz.import_csv([rec_id], {})
643
 
            imported = False
644
 
            while not imported:
645
 
                time.sleep(5)
646
 
                imported = nb != req.search([])
647
 
            return
648
 
        with open(filename, 'r') as csvfile:
649
 
            reader = csv.reader(csvfile, delimiter=',')
650
 
            fields = False
651
 
            data = []
652
 
            for row in reader:
653
 
                if not fields:
654
 
                    fields = row
655
 
                else:
656
 
                    data.append(row)
657
 
            obj = self.db.get(model)
658
 
            if obj and fields and data:
659
 
                obj.import_data(fields, data)
660
 
 
661
 
    @unittest.skipIf(skipMasterCreation, "Creation of coordo from master")
662
 
    def test_00_restore_from_master(self):
663
 
        global skipCreation
664
 
        global skipModules
665
 
        skipCreation = True
666
 
        skipModules = True
667
 
        self.restore_db()
668
 
 
669
 
    @unittest.skipIf(skipModuleUpdate, "update_client installation desactivated")
670
 
    def test_10_install_update_client(self):
671
 
        self.db.connect('admin')
672
 
        self.db.module('update_client').install().do()
673
 
 
674
 
    @unittest.skipIf(skipModules, "Modules installation desactivated")
675
 
    def test_10_install_web_module(self):
676
 
        self.db.connect('admin')
677
 
        self.db.module('sync_client_web').install().do()
678
151
 
679
152
    @unittest.skipIf(skipRegister, "Registration desactivated")
680
 
    def test_20_register_entity(self):
 
153
    def test_10_register_entity(self):
 
154
        if self.db is Synchro: return
 
155
        self.db.connect('admin')
681
156
        Synchro.connect('admin')
682
 
        if not hasattr(config, 'sync_user_admin') or not config.sync_user_admin:
683
 
            Synchro.user(self.db.name).add(self.db.name).addGroups('Sync / User')
684
 
        self.db.connect('admin')
685
 
 
686
 
        oc = get_oc(self.db.name)
687
 
        entity_id = self.db.get('sync.client.entity').search([])
688
 
        data = {
689
 
            'name': self.db.name,
690
 
            'identifier': str(uuid.uuid1()),
691
 
        }
692
 
        data['oc'] = oc
693
 
        if entity_id:
694
 
            entity_data = self.db.get('sync.client.entity').read(entity_id[0])
695
 
            if entity_data['name'] != self.db.name:
696
 
                self.db.get('sync.client.entity').write(entity_id[0], data)
697
 
        else:
698
 
            self.db.get('sync.client.entity').create(data)
699
 
        wiz_data = {'email': config.default_email}
700
 
        wiz_data['oc'] = oc
701
 
        wizard = self.db.wizard('sync.client.register_entity', wiz_data)
 
157
        wizard = self.db.wizard('sync.client.register_entity', {'email':config.default_email})
702
158
        # Fetch instances
 
159
        wizard.next()
703
160
        # Group state
704
161
        wizard.group_state()
705
162
        # Register instance
706
163
        wizard.validate()
707
164
        # Search entity record, server side
708
165
        entities = Synchro.get('sync.server.entity')
709
 
        entity_ids = entities.search([('name','=',self.db.name)])
710
 
        if not len(entity_ids) == 1:
711
 
            self.fail("Cannot find validation request for entity %s!" % self.db.name)
 
166
        ids = entities.search([('name','=',self.db.__name__)])
 
167
        if not len(ids) == 1: raise Exception, "Cannot find validation request for entity %s!" % self.db.__name__
712
168
        # Set parent
713
 
        if self.parent_name is not None:
714
 
            parents = entities.search([('name','=',self.parent_name)])
 
169
        if self.db is not HQ:
 
170
            if self.db is Coordo:
 
171
                parents = entities.search([('name','=','HQ')])
 
172
            elif self.db in (Project, Project2):
 
173
                parents = entities.search([('name','=','Coordo')])
 
174
            else:
 
175
                raise NotImplementedError('Cannot identify database %s' % self.db.__name__)
715
176
            if not parents:
716
 
                self.fail('Cannot find parent entity for %s!' % self.db.name)
717
 
            entities.write(entity_ids, {'parent_id':parents[0]})
718
 
 
719
 
    @unittest.skipIf(skipSync, "Synchronization desactivated")
720
 
    def test_50_synchronize(self):
721
 
        self.db.connect('admin')
722
 
        self.sync()
723
 
 
724
 
    def test_70_create_intermission(self):
725
 
        if isinstance(self, hqn_creation):
726
 
            return True
727
 
 
728
 
        partner = self.hq.db.get('res.partner')
729
 
        account = self.hq.db.get('account.account')
730
 
        partner.create({
731
 
            'name': self.db.name,
732
 
            'partner_type': 'intermission',
733
 
            'customer': False,
734
 
            'supplier': False,
735
 
            'property_account_payable':  account.search([('code','=','30020')])[0],
736
 
            'property_account_receivable': account.search([('code','=','12050')])[0],
737
 
            'city': 'XXX',
738
 
        })
739
 
 
740
 
    @unittest.skipIf(skipCreateUsers, "Create users desactivated")
741
 
    def test_70_create_users(self):
742
 
        if not hasattr(config, 'load_users_file') or not config.load_users_file:
743
 
            return
744
 
 
745
 
        is_hq = isinstance(self, hqn_creation)
746
 
        is_coordo = isinstance(self, coordon_creation)
747
 
        is_project = isinstance(self, projectn_creation)
748
 
 
749
 
        if is_hq or is_coordo or is_project:
750
 
            users = get_users_from_file(config.load_users_file);
751
 
            for u in users:
752
 
                if (is_hq and u['for_hq']) or (is_coordo and u['for_co']) or (is_project and u['for_pr']):
753
 
                    self.db.user(u['login']).add(u['passwd']).addGroups(*u['groups'])
754
 
 
755
 
 
756
 
    @unittest.skipIf(skipModuleData, "Data module installation desactivated")
757
 
    def test_90_install_post_data(self):
758
 
        self.db.connect('admin')
759
 
        if hasattr(config, 'load_data') and config.load_data:
760
 
            for filename in config.load_data:
761
 
                self.import_csv(filename)
762
 
        else:
763
 
            self.db.module('msf_sync_data_post_synchro').install().do().set_notinstalled()
764
 
 
765
 
    def search_account(self, code):
766
 
        account = self.db.get('account.account')
767
 
        ac_ids = account.search([('code', '=', code)])
768
 
        if ac_ids:
769
 
            return ac_ids[0]
770
 
        return False
771
 
 
772
 
    def test_91_configure_company_accounts(self):
773
 
        company_fields = {
774
 
            'salaries_default_account': '30100',
775
 
            'counterpart_hq_entries_default_account': '33010',
776
 
            'import_invoice_default_account': '12011',
777
 
            'intermission_default_counterpart': '14010',
778
 
            'ye_pl_cp_for_bs_debit_bal_account': '69001',
779
 
            'ye_pl_cp_for_bs_credit_bal_account': '79002',
780
 
            'ye_pl_pos_credit_account': '79003',
781
 
            'ye_pl_ne_credit_account': '50000',
782
 
            'ye_pl_pos_debit_account': '51000',
783
 
            'ye_pl_ne_debit_account': '69002',
784
 
            'cheque_debit_account_id': '10210',
785
 
            'cheque_credit_account_id': '10210',
786
 
            'bank_debit_account_id': '10200',
787
 
            'bank_credit_account_id': '10200',
788
 
            'cash_debit_account_id': '10100',
789
 
            'cash_credit_account_id': '10100',
790
 
        }
791
 
        for f in company_fields:
792
 
            company_fields[f] = self.search_account(company_fields[f])
793
 
        self.db.get('res.company').write([1], company_fields)
794
 
 
795
 
    @unittest.skipIf(skipPartner, "Partner creation desactivated")
796
 
    def test_91_instance_partner(self):
797
 
        self.db.connect('admin')
798
 
        account = self.db.get('account.account')
799
 
 
800
 
        res = self.db.get('res.partner')
801
 
        temp_partner = res.search([('name','=','Local Market')])
802
 
        # new CoA (2014-02-20)
803
 
        payable_ids = account.search([('code','=','30020')])
804
 
        if not payable_ids:
805
 
            payable_ids = account.search([('code','=','3000')])
806
 
 
807
 
        receivable_ids = account.search([('code','=','12050')])
808
 
        if not receivable_ids:
809
 
            receivable_ids = account.search([('code','=','1205')])
810
 
        if temp_partner:
811
 
            # set account values for local market
812
 
            self.db.write('res.partner', temp_partner,{
813
 
                'property_account_payable' : payable_ids[0],
814
 
                'property_account_receivable' : receivable_ids[0],
815
 
                'city': 'Geneva',
816
 
            })
817
 
        temp_partner = res.search([('name','=',self.db.name)])
818
 
        if temp_partner:
819
 
            # set account values for the default user
820
 
            self.db.write('res.partner', temp_partner,{
821
 
                'property_account_payable' : payable_ids[0],
822
 
                'property_account_receivable' : receivable_ids[0],
823
 
            })
824
 
 
825
 
    @unittest.skipIf(skipOpenPeriod, "Open Period desactivated")
826
 
    def test_92_open_period(self):
827
 
        self.db.connect('admin')
828
 
        today = time.strftime('%Y-%m-%d')
829
 
        month = time.strftime('%m')
830
 
        # search current fiscalyear
831
 
        fy_ids = self.db.search_data('account.fiscalyear', [('date_start', '<=', today), ('date_stop', '>=', today)])
832
 
        if not fy_ids:
833
 
            create_fy_wiz = self.db.get('account.period.create')
834
 
            wiz_id = create_fy_wiz.create({'fiscalyear': 'current'})
835
 
            create_fy_wiz.account_period_create_periods([wiz_id])
836
 
            fy_ids = self.db.search_data('account.fiscalyear', [('date_start', '<=', today), ('date_stop', '>=', today)])
837
 
 
838
 
        assert len(fy_ids) > 0, "No fiscalyear found!"
839
 
        period_ids = self.db.search_data('account.period', [('fiscalyear_id', 'in', fy_ids), ('number', '<=', month), ('state', '=', 'created')])
840
 
        # change all period by draft state (should use action_set_state but openerplib doesn't give way to do this)
841
 
        # as it's to open period from created to draft state, it's not very important
842
 
        self.db.write('account.period', period_ids, {'state': 'draft'})
843
 
 
844
 
    def set_analytic_loss(self, db, code):
845
 
        db.connect('admin')
846
 
        ana_obj = db.get('account.analytic.account')
847
 
        ids = ana_obj.search([('code', '=', code)])
848
 
        if ids:
849
 
            ana_obj.write(ids[0], {'for_fx_gain_loss': True})
850
 
 
851
 
    def test_93_set_gain_loss(self):
852
 
        to_hq = False
853
 
        code = False
854
 
        if isinstance(self, projectn_creation):
855
 
            code = "HT%d%d1" % (self.parent.index, self.index)
856
 
        elif isinstance(self, coordon_creation):
857
 
            code = "HT%d01" % (self.index)
858
 
            if self.index == 1:
859
 
                to_hq = True
860
 
        if code:
861
 
            self.db.get('ir.config_parameter').set_param('INIT_CC_FX_GAIN', code)
862
 
            if to_hq:
863
 
                self.set_analytic_loss(self.hq.db, code)
864
 
 
865
 
    def test_95_create_registers(self):
866
 
        if isinstance(self, hqn_creation):
867
 
            return True
868
 
 
869
 
        reg = {'EUR': {}, 'CHF': {}}
870
 
        for j_type, account_code in [('bank', '10200'), ('cash', '10100'), ('cheque', '10210')]:
871
 
            account_id = self.db.get('account.account').search([('code', '=', account_code)])[0]
872
 
            for cur in ['EUR', 'CHF']:
873
 
                data = {
874
 
                    'name': '%s %s %s' % (j_type, self.db.name, cur),
875
 
                    'code': '%s%s%s' % (j_type, self.db.name[-2:], cur),
876
 
                    'type': j_type,
877
 
                    'currency': self.db.get('res.currency').search([('name', '=', cur)])[0],
878
 
                    'default_credit_account_id': account_id,
879
 
                    'default_debit_account_id': account_id,
880
 
                }
881
 
                get_ana = self.db.get('account.journal').onchange_type(False, j_type, False)
882
 
                data['analytic_journal_id'] = get_ana.get('value', {}).get('analytic_journal_id', False)
883
 
                if j_type == 'cheque':
884
 
                    if not reg[cur].get('bank'):
885
 
                        continue
886
 
                    data['bank_journal_id'] = reg[cur]['bank']
887
 
 
888
 
                reg[cur][j_type] = self.db.get('account.journal').create(data)
889
 
 
890
 
    def test_95_create_stock_cu(self):
891
 
        if isinstance(self, hqn_creation):
892
 
            return True
893
 
 
894
 
        stock_wiz = self.db.get('stock.location.configuration.wizard')
895
 
        w_id = stock_wiz.create({'location_usage': 'consumption_unit', 'location_type': 'internal', 'location_name': 'IntCU'})
896
 
        stock_wiz.confirm_creation(w_id)
897
 
        w_id = stock_wiz.create({'location_usage': 'consumption_unit', 'location_type': 'customer', 'location_name': 'ExtCU'})
898
 
        stock_wiz.confirm_creation(w_id)
899
 
 
900
 
    def test_99_add_shortcut(self):
901
 
        self.db.connect('admin')
902
 
        menu_to_add = ['sync_client.sync_wiz_menu', 'sync_client.sync_monitor_menu']
903
 
        for menu in menu_to_add:
904
 
            module, xml = menu.split('.')
905
 
            menu_id = self.db.get('ir.model.data').get_object_reference(module, xml)[1]
906
 
            menu_name = self.db.get('ir.ui.menu').name_get([menu_id])[0][1]
907
 
            try:
908
 
                self.db.get('ir.ui.view_sc').create({'res_id': menu_id, 'name': menu_name})
909
 
            except:
910
 
                raise
911
 
 
912
 
    @unittest.skipIf(skipSync, "Synchronization desactivated")
913
 
    def test_99_synchronize(self):
914
 
        self.db.connect('admin')
915
 
        self.sync()
916
 
 
917
 
# Replicable class to create hq n
918
 
class hqn_creation(client_creation, unittest.TestCase):
919
 
    name_format = "%(db)s_HQ%(ind)d"
920
 
 
921
 
    @unittest.skipIf(skipGroups, "Group creation desactivated")
922
 
    def test_30_make_groups_coordo(self):
923
 
        self.add_to_group('Coordinations of %s' % self.db.name, 'COORDINATIONS')
924
 
        self.add_to_group('OC_%02d' % self.index, 'OC')
925
 
        for i in range(1, coordo_count+1):
926
 
            self.add_to_group('HQ%s + Mission %s' % (self.index, i), 'HQ + MISSION')
927
 
        entities = Synchro.get('sync.server.entity')
928
 
        entity_ids = entities.search([('name','=',self.db.name)])
929
 
        entities.validate_action(entity_ids)
930
 
 
931
 
    @unittest.skipIf(skipPropInstance, "Proprietary Instance creation desactivated")
932
 
    def test_40_prop_instance(self):
933
 
        self.db.connect('admin')
934
 
        if self.db.search_data('msf.instance', [('instance','=',self.db.name)]):
935
 
            self.skipTest("Proprietary Instance already exists")
936
 
        self.make_prop_instance(self.db, {
937
 
            'level' : 'section',
938
 
            'reconcile_prefix' : self.prefix,
939
 
            'move_prefix' : self.prefix,
940
 
        })
941
 
 
942
 
    @unittest.skipIf(skipConfig, "Modules configuration desactivated")
943
 
    def test_41_configuration_wizards(self):
944
 
        self.db.connect('admin')
945
 
        self.configure()
946
 
 
947
 
    @unittest.skipIf(skipModuleData, "Data module installation desactivated")
948
 
    def test_42_install_data_client(self):
949
 
        self.db.connect('admin')
950
 
        if hasattr(config, 'load_hq_data') and config.load_hq_data:
951
 
            for filename in config.load_hq_data:
952
 
                self.import_csv(filename)
953
 
        else:
954
 
            self.db.module('msf_sync_data_hq').install().do().set_notinstalled()
955
 
 
956
 
        if self.db.get('ir.model').search([('model', '=', 'hr.payment.method')]):
957
 
            for x in ['ESP', 'CHQ', 'VIR']:
958
 
                self.db.get('hr.payment.method').create({'name': x})
959
 
 
960
 
        # duplicate as UniData
961
 
        if hq_count > 1:
962
 
            data = [
963
 
                'DORADIDA15T',
964
 
                'DINJCEFA1V-',
965
 
                'ADAPCABL1S-',
966
 
                'ADAPCABL2S-',
967
 
                'ADAPCART02-',
968
 
            ]
969
 
            prod = self.db.get('product.product')
970
 
            unidata_id = self.db.get('ir.model.data').get_object_reference('product_attributes', 'int_6')[1]
971
 
            msfid = 100
972
 
            for code in data:
973
 
                p_id = prod.search([('default_code', '=', code)])
974
 
                if p_id:
975
 
                    newcode = 'HQ%s%s' % (self.index, code)
976
 
                    copy_id = prod.copy(p_id[0], {'default_code': newcode, 'international_status': unidata_id, 'msfid': msfid})
977
 
                    prod.write([copy_id], {'name': newcode})
978
 
                msfid += 10
979
 
 
980
 
    def test_41_load_rates(self):
981
 
        cur_dir = os.path.dirname(os.path.realpath(__file__))
982
 
 
983
 
        cur_to_load = config.default_currency
984
 
        hq_name = self.db and self.db.name and re.findall(r'HQ[0-9]+', self.db.name)
985
 
        if hq_name and hasattr(config, 'currency_tree'):
986
 
            cur_to_load = config.currency_tree.get(hq_name[-1], config.default_currency)
987
 
 
988
 
        rate_file = os.path.join(cur_dir, 'data', '%s.txt' % cur_to_load)
989
 
        if os.path.isfile(rate_file):
990
 
            rate_obj = self.db.get('res.currency')
991
 
            fx_rate_obj = self.db.get('res.currency.rate')
992
 
            rate_ids = rate_obj.search([('active', 'in', ['t', 'f'])])
993
 
            rate_dict = {}
994
 
            for x in rate_obj.read(rate_ids, ['name']):
995
 
                rate_dict[x['name']] = x['id']
996
 
            fx_rate_obj.create({'currency_id': rate_dict[cur_to_load.upper()], 'rate': 1, 'name': '2016-01-01'})
997
 
            f = open(rate_file, 'r')
998
 
            date = False
999
 
            for data in f:
1000
 
                data = data.rstrip()
1001
 
                if data[0] != ' ':
1002
 
                    date = data
1003
 
                elif data[0] == ' ' and ':' in data:
1004
 
                    cur, rate = data[1:].split(':')
1005
 
                    if date and rate_dict.get(cur):
1006
 
                        fx_rate_obj.create({'currency_id': rate_dict[cur], 'rate': rate, 'name': date})
1007
 
 
1008
 
    @unittest.skipIf(skipManualConfig, "Manual link on analytic account destination desactivated")
1009
 
    def test_43_manual_link_on_analytic_account_destination(self):
1010
 
        self.db.connect('admin')
1011
 
        # new CoA (2014-02-20)
1012
 
        link_ids = self.db.search_data('account.destination.link', [])
1013
 
        if not link_ids:
1014
 
            account_ids = self.db.search_data('account.account', [('type','!=','view'),('user_type.code','=','expense')])
1015
 
            analytic_account_ids = self.db.search_data('account.analytic.account', [('name', 'in', ['Expatriates','National Staff','Operations','Support'])])
1016
 
            self.db.write('account.analytic.account',  analytic_account_ids, {'destination_ids': [(6, 0, account_ids)]})
1017
 
 
1018
 
 
1019
 
    @unittest.skipIf(skipLoadExtraFiles, "Load Extra Data Files desactivated")
1020
 
    def test_46_load_extra_data_files(self):
1021
 
        if not hasattr(config, 'load_extra_files') or not config.load_extra_files:
1022
 
            return
1023
 
 
1024
 
        self.db.connect('admin')
1025
 
        for filename in config.load_extra_files:
1026
 
            self.import_csv(get_file_from_source(filename))
1027
 
 
1028
 
    @unittest.skipIf(skipLoadUACFile, "Load UAC File desactivated")
1029
 
    def test_45_load_uac_file(self):
1030
 
        if not hasattr(config, 'load_uac_file') or not config.load_uac_file:
1031
 
            return
1032
 
 
1033
 
        self.db.connect('admin')
1034
 
 
1035
 
        f = open(get_file_from_source(config.load_uac_file), 'rb')
1036
 
        data = base64.b64encode(f.read()).decode('utf8')
1037
 
        f.close()
1038
 
 
1039
 
        wiz = self.db.get('user.access.configurator')
1040
 
        rec_id = wiz.create({'file_to_import_uac': data})
1041
 
        try:
1042
 
            wiz.do_process_uac([rec_id])
1043
 
        except:
1044
 
            pass
1045
 
        user_ids = self.db.get('res.users').search([('id', '!=', 1)])
1046
 
        if user_ids:
1047
 
            self.db.get('res.users').write(user_ids, {'password': bcrypt.hash(config.admin_password)})
1048
 
 
1049
 
    def test_70_create_intersection(self):
1050
 
        partner = self.db.get('res.partner')
1051
 
        account = self.db.get('account.account')
1052
 
        pricelist = self.db.get('product.pricelist')
1053
 
        purch_eur = pricelist.search([('type', '=', 'purchase'), ('currency_id.name', '=', 'EUR')])
1054
 
        sale_eur = pricelist.search([('type', '=', 'sale'), ('currency_id.name', '=', 'EUR')])
1055
 
        for tc in test_cases:
1056
 
            if (issubclass(tc, coordon_creation) or issubclass(tc, projectn_creation)) and tc.hq.index != self.index:
1057
 
                if tc.db is None:
1058
 
                    db_name = tc.name_format % tc.getNameFormat()
1059
 
                else:
1060
 
                    db_name = tc.db.name
1061
 
                partner.create({
1062
 
                    'name': db_name,
1063
 
                    'partner_type': 'section',
1064
 
                    'po_by_project': 'project',
1065
 
                    'customer': True,
1066
 
                    'supplier': True,
1067
 
                    'property_account_payable':  account.search([('code','=','30010')])[0],
1068
 
                    'property_account_receivable': account.search([('code','=','12010')])[0],
1069
 
                    'city': 'XXX',
1070
 
                    'property_product_pricelist_purchase': purch_eur[0],
1071
 
                    'property_product_pricelist': sale_eur[0],
1072
 
                })
1073
 
 
1074
 
    def test_99_create_esc(self):
1075
 
        account = self.db.get('account.account')
1076
 
        self.db.get('res.partner').create({
1077
 
            'name': 'ESC',
1078
 
            'partner_type': 'esc',
1079
 
            'po_by_project': 'project',
1080
 
            'supplier': True,
1081
 
            'customer': False,
1082
 
            'property_account_payable':  account.search([('code','=','30010')])[0],
1083
 
            'property_account_receivable': account.search([('code','=','12050')])[0],
1084
 
            'city': 'XXX',
1085
 
        })
1086
 
 
1087
 
 
1088
 
# Replicable class to create coordo n
1089
 
class coordon_creation(client_creation):
1090
 
    name_format = "%(db)s_HQ%(pind)dC%(ind)d"
1091
 
 
1092
 
    @unittest.skipIf(skipGroups, "Group creation desactivated")
1093
 
    def test_30_make_groups_coordo(self):
1094
 
        self.add_to_group('OC_%02d' % self.hq.index, 'OC')
1095
 
        self.add_to_group('Coordinations of %s' % self.hq.db.name, 'COORDINATIONS')
1096
 
        self.add_to_group('Mission %s-%s' % (self.hq.index, self.index), 'MISSION')
1097
 
        self.add_to_group('HQ%s + Mission %s' % (self.hq.index, self.index), 'HQ + MISSION')
1098
 
        entities = Synchro.get('sync.server.entity')
1099
 
        entity_ids = entities.search([('name','=',self.db.name)])
1100
 
        entities.validate_action(entity_ids)
1101
 
 
1102
 
 
1103
 
    @unittest.skipIf(skipPropInstance, "Proprietary Instance creation desactivated")
1104
 
    def test_40_prop_instance(self):
1105
 
        self.hq.db.connect('admin')
1106
 
        if self.hq.db.search_data('msf.instance', [('instance','=',self.db.name)]):
1107
 
            self.skipTest("Proprietary Instance already exists")
1108
 
        self.make_prop_instance(self.hq.db, {
1109
 
            'level' : 'coordo',
1110
 
            'reconcile_prefix' : self.prefix,
1111
 
            'move_prefix' : self.prefix,
1112
 
            'parent_id' : self.hq.db.search_data('msf.instance', [('instance','=',self.hq.db.name)])[0],
1113
 
        }, self.hq)
1114
 
 
1115
 
    @unittest.skipIf(skipConfig, "Modules configuration desactivated")
1116
 
    def test_60_configuration_wizards(self):
1117
 
        self.db.connect('admin')
1118
 
        self.configure()
1119
 
 
1120
 
    @unittest.skipIf(skipModuleData, "Data module installation desactivated")
1121
 
    def test_61_install_data_client(self):
1122
 
        self.db.connect('admin')
1123
 
        self.db.module('msf_sync_data_coordo').install().do().set_notinstalled()
1124
 
        partner_obj = self.db.get('res.partner')
1125
 
        p_ids = partner_obj.search([('name', '=', 'ESC'), ('active', '=', False)])
1126
 
        if p_ids:
1127
 
            partner_obj.write(p_ids, {'active': True})
1128
 
 
1129
 
 
1130
 
# Replicable class to create project n
1131
 
class projectn_creation(client_creation):
1132
 
    name_format = "%(db)s_HQ%(ppind)dC%(pind)dP%(ind)d"
1133
 
 
1134
 
    @unittest.skipIf(skipGroups, "Group creation desactivated")
1135
 
    def test_30_make_groups_coordo(self):
1136
 
        self.add_to_group('OC_%02d' % self.hq.index, 'OC')
1137
 
        self.add_to_group('Mission %s-%s' % (self.hq.index, self.parent.index), 'MISSION')
1138
 
        self.add_to_group('HQ%s + Mission %s' % (self.hq.index, self.parent.index), 'HQ + MISSION')
1139
 
        entities = Synchro.get('sync.server.entity')
1140
 
        entity_ids = entities.search([('name','=',self.db.name)])
1141
 
        entities.validate_action(entity_ids)
1142
 
 
1143
 
    @unittest.skipIf(skipGroups, "Group creation desactivated")
1144
 
    def test_31_make_groups_project(self):
1145
 
        Synchro.connect('admin')
1146
 
        entity_ids = Synchro.get('sync.server.entity').search([('name','=',self.db.name)])
 
177
                raise Exception('Cannot find parent entity for %s!' % self.db.__name__)
 
178
            entities.write(ids, {'parent_id':parents[0]})
 
179
        # Server accept validation
 
180
        entities.validate_action(ids)
1147
181
        # Add entity to groups
1148
182
        group = Synchro.get('sync.server.entity_group')
1149
 
        group.write(group.search([('name','=','Mission1')]), {
1150
 
            'entity_ids' : [(4,entity_ids[0])],
1151
 
        })
1152
 
 
1153
 
    @unittest.skipIf(skipPropInstance, "Proprietary Instance creation desactivated")
1154
 
    def test_40_prop_instance(self):
1155
 
        self.hq.db.connect('admin')
1156
 
        if self.hq.db.search_data('msf.instance', [('instance','=',self.db.name)]):
1157
 
            self.skipTest("Proprietary Instance already exists")
1158
 
        self.make_prop_instance(self.hq.db, {
1159
 
            'level' : 'project',
1160
 
            'reconcile_prefix' : self.prefix,
1161
 
            'move_prefix' : self.prefix,
1162
 
            'parent_id' : self.hq.db.search_data('msf.instance', [('instance','=',self.parent_name)])[0],
1163
 
        }, self.parent)
1164
 
 
1165
 
    @unittest.skipIf(skipConfig, "Modules configuration desactivated")
1166
 
    def test_60_configuration_wizards(self):
1167
 
        self.db.connect('admin')
1168
 
        self.configure()
1169
 
 
1170
 
 
1171
 
class verbose(unittest.TestCase):
1172
 
    def test_10_show_dbs(self):
1173
 
        warn("\n"+"-" * 40)
1174
 
        for tc_hq in [tc for tc in test_cases if issubclass(tc, hqn_creation)]:
1175
 
            warn( " * %s" % hqn_creation.name_format % tc_hq.getNameFormat())
1176
 
            for tc in [tc for tc in test_cases if issubclass(tc, coordon_creation) \
1177
 
                       and tc.parent is tc_hq]:
1178
 
                warn( "    - %s" % coordon_creation.name_format % tc.getNameFormat())
1179
 
                for tp in [tp for tp in test_cases if issubclass(tp, projectn_creation) \
1180
 
                           and tp.parent is tc]:
1181
 
                    warn( "        + %s" % projectn_creation.name_format % tp.getNameFormat())
1182
 
            warn("-" * 40)
1183
 
 
1184
 
 
1185
 
 
1186
 
# Base Install
1187
 
test_cases = [verbose, update_branches, server_creation]
1188
 
 
1189
 
# Create HQ classes
1190
 
if not hasattr(config, 'instance_tree') or not config.instance_tree:
1191
 
    config.instance_tree = {}
1192
 
    for i in range(1, hq_count+1):
1193
 
        config.instance_tree['HQ%d'%i] = {}
1194
 
        for ci in range(1, coordo_count+1):
1195
 
            config.instance_tree['HQ%d'%i]['C%d'%ci] = []
1196
 
            for pi in range(1, project_count+1):
1197
 
                config.instance_tree['HQ%d'%i]['C%d'%ci].append('P%d'%pi)
1198
 
else:
1199
 
    hq_count = len(list(config.instance_tree.keys()))
1200
 
    coordo_count = max([len(list(x.values())) for x in list(config.instance_tree.values())])
1201
 
 
1202
 
hq_index = 0
1203
 
for hq, coordos in config.instance_tree.items():
1204
 
    hq_index += 1
1205
 
    test_cases.append( type("HQ%d_creation" % hq_index, (hqn_creation,unittest.TestCase), {
1206
 
        'prefix' : 'HQ%s'%hq_index,
1207
 
        'index' : hq_index,
1208
 
    }) )
1209
 
    # Make testcase visible for importation
1210
 
    globals()[test_cases[-1].__name__] = test_cases[-1]
1211
 
 
1212
 
    coordo_index = 0
1213
 
    # Create Coordo classes
1214
 
    for coordo in sorted(coordos.keys()):
1215
 
        coordo_index += 1
1216
 
        test_cases.append( type("HQ%d_C%d_creation" % (hq_index, coordo_index), (coordon_creation,unittest.TestCase), {
1217
 
            'prefix' : 'C%s%s' % (hq_index, coordo_index),
1218
 
            'index' : coordo_index,
1219
 
            'parent' : globals()["HQ%d_creation" % hq_index],
1220
 
        }) )
1221
 
        test_cases[-1].hq = test_cases[-1].parent
1222
 
        # Make testcase visible for importation
1223
 
        globals()[test_cases[-1].__name__] = test_cases[-1]
1224
 
 
1225
 
        project_index = 0
1226
 
        # Create Project classes
1227
 
        for pi in coordos[coordo]:
1228
 
            project_index += 1
1229
 
            test_cases.append( type("HQ%d_C%d_P%d_creation" % (hq_index, coordo_index, project_index), (projectn_creation,unittest.TestCase), {
1230
 
                'prefix' : 'P%s%s%s'%(hq_index, coordo_index, project_index),
1231
 
                'index' : project_index,
1232
 
                'parent' : globals()["HQ%d_C%d_creation" % (hq_index, coordo_index)],
1233
 
            }) )
1234
 
            test_cases[-1].hq = test_cases[-1].parent.parent
1235
 
            # Make testcase visible for importation
1236
 
            globals()[test_cases[-1].__name__] = test_cases[-1]
1237
 
 
1238
 
 
1239
 
# Push last_sync test at last
1240
 
test_cases.append(last_sync)
1241
 
 
1242
 
# activate inter partners
1243
 
test_cases.append(activate_inter_partner)
1244
 
 
1245
 
# and dump
1246
 
test_cases.append(dump_all)
1247
 
 
 
183
        group.write(group.search([('name','=','Section')]), {
 
184
            'entity_ids' : [(4,ids[0])],
 
185
        })
 
186
        group.write(group.search([('name','=','Mission')]), {
 
187
            'entity_ids' : [(4,ids[0])],
 
188
        })
 
189
 
 
190
    @unittest.skipIf(skipSync, "Synchronization desactivated")
 
191
    def test_40_synchronize(self):
 
192
        self.db.connect('admin')
 
193
        self.sync()
 
194
 
 
195
class hq_creation(client_creation, unittest.TestCase):
 
196
    db = HQ
 
197
 
 
198
    @unittest.skipIf(skipModuleTest, "client_test installation desactivated")
 
199
    def test_20_install_test_client(self):
 
200
        self.db.connect('admin')
 
201
        self.db.module('sync_client_test').install().do()
 
202
 
 
203
    @unittest.skipIf(skipConfig, "Modules configuration desactivated")
 
204
    def test_30_configuration_wizards(self):
 
205
        self.db.connect('admin')
 
206
        self.configure()
 
207
 
 
208
class coordo_creation(client_creation, unittest.TestCase):
 
209
    db = Coordo
 
210
 
 
211
    @unittest.skipIf(skipConfig, "Modules configuration desactivated")
 
212
    def test_50_configuration_wizards(self):
 
213
        self.db.connect('admin')
 
214
        self.configure()
 
215
 
 
216
class project_creation(client_creation, unittest.TestCase):
 
217
    db = Project
 
218
 
 
219
    @unittest.skipIf(skipConfig, "Modules configuration desactivated")
 
220
    def test_50_configuration_wizards(self):
 
221
        self.db.connect('admin')
 
222
        self.configure()
 
223
 
 
224
class project2_creation(client_creation, unittest.TestCase):
 
225
    db = Project2
 
226
 
 
227
    @unittest.skipIf(skipConfig, "Modules configuration desactivated")
 
228
    def test_50_configuration_wizards(self):
 
229
        self.db.connect('admin')
 
230
        self.configure()
 
231
 
 
232
test_cases = (synchro_creation, hq_creation, coordo_creation, project_creation, project2_creation)
 
233
#test_cases = (synchro_creation,)
 
234
#test_cases = (hq_creation,)
 
235
#test_cases = (coordo_creation,)
 
236
#test_cases = (synchro_creation, hq_creation, coordo_creation,)
 
237
#test_cases = (project_creation,project2_creation,)
 
238
#test_cases = (project2_creation,)
1248
239
 
1249
240
def load_tests(loader, tests, pattern):
1250
241
    suite = unittest.TestSuite()
1253
244
        suite.addTests(tests)
1254
245
    return suite
1255
246
 
1256
 
 
1257
247
if __name__ == '__main__':
1258
 
    if o.log_to_file:
1259
 
        if not os.path.exists(dir_to_dump):
1260
 
            os.makedirs(dir_to_dump)
1261
 
        f = open(os.path.join(dir_to_dump, 'script_result.log'), "w")
1262
 
        stream = f
1263
 
    else:
1264
 
        stream = sys.stderr
1265
 
    unittest.main(testRunner=unittest.TextTestRunner(stream,failfast=True, verbosity=2))
1266
 
    if o.log_to_file:
1267
 
        f.close()
 
248
    unittest.main(failfast=True, verbosity=2)
 
249