chrono/chrono/manager/utils.py

127 lines
4.4 KiB
Python

# chrono - agendas system
# Copyright (C) 2016-2017 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import collections
import itertools
from django.contrib.auth.models import Group
from django.db import transaction
from django.db.models import Q
from chrono.agendas.models import (
Agenda,
AgendaImportError,
Category,
EventsType,
Resource,
SharedCustodySettings,
UnavailabilityCalendar,
)
def export_site(
agendas=True,
unavailability_calendars=True,
events_types=True,
resources=True,
categories=True,
shared_custody=True,
):
'''Dump site objects to JSON-dumpable dictionnary'''
data = collections.OrderedDict()
if categories:
data['categories'] = [x.export_json() for x in Category.objects.all()]
if resources:
data['resources'] = [x.export_json() for x in Resource.objects.all()]
if events_types:
data['events_types'] = [x.export_json() for x in EventsType.objects.all()]
if unavailability_calendars:
data['unavailability_calendars'] = [x.export_json() for x in UnavailabilityCalendar.objects.all()]
if agendas:
qs1 = Agenda.objects.filter(~Q(kind='virtual'))
qs2 = Agenda.objects.filter(kind='virtual')
data['agendas'] = [x.export_json() for x in itertools.chain(qs1, qs2)]
if shared_custody:
data['shared_custody_settings'] = SharedCustodySettings.get_singleton().export_json()
return data
def import_site(data, if_empty=False, clean=False, overwrite=False):
# pylint: disable=too-many-boolean-expressions
if if_empty and (
Agenda.objects.exists()
or UnavailabilityCalendar.objects.exists()
or EventsType.objects.exists()
or Resource.objects.exists()
or Category.objects.exists()
):
return
if clean:
Agenda.objects.all().delete()
SharedCustodySettings.objects.all().delete()
UnavailabilityCalendar.objects.all().delete()
EventsType.objects.all().delete()
Resource.objects.all().delete()
Category.objects.all().delete()
results = {
key: collections.defaultdict(list)
for key in [
'agendas',
'unavailability_calendars',
'events_types',
'resources',
'categories',
]
}
role_names = set()
for key in ['agendas', 'unavailability_calendars']:
objs = data.get(key, [])
role_names = role_names.union(
{name for data in objs for _, name in data.get('permissions', {}).items() if name}
)
shared_custody_settings = data.get('shared_custody_settings')
if shared_custody_settings and shared_custody_settings['management_role']:
role_names.add(shared_custody_settings['management_role'])
existing_roles = Group.objects.filter(name__in=role_names)
if existing_roles.count() != len(role_names):
existing_roles_names = set(existing_roles.values_list('name', flat=True))
raise AgendaImportError('Missing roles: "%s"' % ', '.join(role_names - existing_roles_names))
with transaction.atomic():
for cls, key in (
(Category, 'categories'),
(Resource, 'resources'),
(EventsType, 'events_types'),
(UnavailabilityCalendar, 'unavailability_calendars'),
(Agenda, 'agendas'),
):
objs = data.get(key, [])
for obj in objs:
created, obj = cls.import_json(obj, overwrite=overwrite)
results[key]['all'].append(obj)
if created:
results[key]['created'].append(obj)
else:
results[key]['updated'].append(obj)
SharedCustodySettings.import_json(data.get('shared_custody_settings', {}))
return results