virtual agendas: handle import/export (#40057)
This commit is contained in:
parent
ec474b46d2
commit
7c707f6674
|
@ -203,7 +203,6 @@ class Agenda(models.Model):
|
|||
return gcd
|
||||
|
||||
def export_json(self):
|
||||
# TODO VIRTUAL
|
||||
agenda = {
|
||||
'label': self.label,
|
||||
'slug': self.slug,
|
||||
|
@ -220,6 +219,9 @@ class Agenda(models.Model):
|
|||
elif self.kind == 'meetings':
|
||||
agenda['meetingtypes'] = [x.export_json() for x in self.meetingtype_set.all()]
|
||||
agenda['desks'] = [desk.export_json() for desk in self.desk_set.all()]
|
||||
elif self.kind == 'virtual':
|
||||
agenda['excluded_timeperiods'] = [x.export_json() for x in self.excluded_timeperiods.all()]
|
||||
agenda['real_agendas'] = [{'slug': x.slug, 'kind': x.kind} for x in self.real_agendas.all()]
|
||||
return agenda
|
||||
|
||||
@classmethod
|
||||
|
@ -231,6 +233,9 @@ class Agenda(models.Model):
|
|||
elif data['kind'] == 'meetings':
|
||||
meetingtypes = data.pop('meetingtypes')
|
||||
desks = data.pop('desks')
|
||||
elif data['kind'] == 'virtual':
|
||||
excluded_timeperiods = data.pop('excluded_timeperiods')
|
||||
real_agendas = data.pop('real_agendas')
|
||||
for permission in ('view', 'edit'):
|
||||
if permissions.get(permission):
|
||||
try:
|
||||
|
@ -257,6 +262,23 @@ class Agenda(models.Model):
|
|||
for desk in desks:
|
||||
desk['agenda'] = agenda
|
||||
Desk.import_json(desk).save()
|
||||
elif data['kind'] == 'virtual':
|
||||
if overwrite:
|
||||
TimePeriod.objects.filter(agenda=agenda).delete()
|
||||
VirtualMember.objects.filter(virtual_agenda=agenda).delete()
|
||||
for excluded_timeperiod in excluded_timeperiods:
|
||||
excluded_timeperiod['agenda'] = agenda
|
||||
TimePeriod.import_json(excluded_timeperiod).save()
|
||||
for real_agenda in real_agendas:
|
||||
real_agenda = Agenda.objects.get(slug=real_agenda['slug'], kind=real_agenda['kind'])
|
||||
try:
|
||||
vm, created = VirtualMember.objects.get_or_create(
|
||||
virtual_agenda=agenda, real_agenda=real_agenda
|
||||
)
|
||||
vm.clean()
|
||||
except ValidationError as exc:
|
||||
raise AgendaImportError(' '.join(exc.messages))
|
||||
|
||||
return created
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,10 @@
|
|||
# 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 itertools
|
||||
|
||||
from django.db import transaction
|
||||
from django.db.models import Q
|
||||
|
||||
from chrono.agendas.models import Agenda, AgendaImportError
|
||||
|
||||
|
@ -22,7 +25,9 @@ from chrono.agendas.models import Agenda, AgendaImportError
|
|||
def export_site():
|
||||
'''Dump site objects to JSON-dumpable dictionnary'''
|
||||
data = {}
|
||||
data['agendas'] = [x.export_json() for x in Agenda.objects.all()]
|
||||
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)]
|
||||
return data
|
||||
|
||||
|
||||
|
|
|
@ -16,7 +16,16 @@ from django.core.management import call_command, CommandError
|
|||
from django.utils.encoding import force_bytes
|
||||
from django.utils.timezone import make_aware
|
||||
|
||||
from chrono.agendas.models import Agenda, Event, TimePeriod, Desk, TimePeriodException, AgendaImportError
|
||||
from chrono.agendas.models import (
|
||||
Agenda,
|
||||
Event,
|
||||
TimePeriod,
|
||||
Desk,
|
||||
TimePeriodException,
|
||||
AgendaImportError,
|
||||
MeetingType,
|
||||
VirtualMember,
|
||||
)
|
||||
from chrono.manager.utils import import_site
|
||||
|
||||
from test_api import some_data, meetings_agenda, time_zone, mock_now
|
||||
|
@ -179,3 +188,91 @@ def test_import_export_permissions(app, some_data, meetings_agenda):
|
|||
agenda = Agenda.objects.get(slug=meetings_agenda.slug)
|
||||
assert agenda.view_role == group1
|
||||
assert agenda.edit_role == group2
|
||||
|
||||
|
||||
def test_import_export_virtual_agenda(app):
|
||||
virtual_agenda = Agenda.objects.create(label='Virtual Agenda', kind='virtual')
|
||||
output = get_output_of_command('export_site')
|
||||
payload = json.loads(output)
|
||||
assert len(payload['agendas']) == 1
|
||||
virtual_agenda.delete()
|
||||
import_site(json.loads(output), overwrite=True)
|
||||
|
||||
virtual_agenda = Agenda.objects.get(label='Virtual Agenda', slug='virtual-agenda', kind='virtual')
|
||||
assert virtual_agenda.minimal_booking_delay is None
|
||||
assert virtual_agenda.maximal_booking_delay is None
|
||||
assert virtual_agenda.real_agendas.count() == 0
|
||||
assert virtual_agenda.excluded_timeperiods.count() == 0
|
||||
|
||||
# add booking delay
|
||||
virtual_agenda.minimal_booking_delay = 2
|
||||
virtual_agenda.maximal_booking_delay = 10
|
||||
virtual_agenda.save()
|
||||
output = get_output_of_command('export_site')
|
||||
payload = json.loads(output)
|
||||
virtual_agenda.delete()
|
||||
import_site(json.loads(output), overwrite=True)
|
||||
virtual_agenda = Agenda.objects.get(label='Virtual Agenda', slug='virtual-agenda', kind='virtual')
|
||||
assert virtual_agenda.minimal_booking_delay == 2
|
||||
assert virtual_agenda.maximal_booking_delay == 10
|
||||
|
||||
# add excluded timeperiods
|
||||
tp1 = TimePeriod.objects.create(
|
||||
agenda=virtual_agenda, weekday=1, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
|
||||
)
|
||||
tp2 = TimePeriod.objects.create(
|
||||
agenda=virtual_agenda, weekday=2, start_time=datetime.time(12, 0), end_time=datetime.time(13, 0)
|
||||
)
|
||||
output = get_output_of_command('export_site')
|
||||
payload = json.loads(output)
|
||||
virtual_agenda.delete()
|
||||
tp1.delete()
|
||||
tp2.delete()
|
||||
import_site(json.loads(output), overwrite=True)
|
||||
virtual_agenda = Agenda.objects.get(label='Virtual Agenda', slug='virtual-agenda', kind='virtual')
|
||||
assert virtual_agenda.excluded_timeperiods.count() == 2
|
||||
tp1 = TimePeriod.objects.get(
|
||||
agenda=virtual_agenda, weekday=1, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
|
||||
)
|
||||
tp2 = TimePeriod.objects.get(
|
||||
agenda=virtual_agenda, weekday=2, start_time=datetime.time(12, 0), end_time=datetime.time(13, 0)
|
||||
)
|
||||
|
||||
|
||||
def test_import_export_virtual_agenda_with_included_agenda(app):
|
||||
virtual_agenda = Agenda.objects.create(label='Virtual Agenda', kind='virtual')
|
||||
foo_agenda = Agenda.objects.create(label='Foo', kind='meetings')
|
||||
bar_agenda = Agenda.objects.create(label='Bar', kind='meetings')
|
||||
mt1 = MeetingType.objects.create(agenda=foo_agenda, label='Meeting Type', duration=30)
|
||||
mt2 = MeetingType.objects.create(agenda=bar_agenda, label='Meeting Type', duration=30)
|
||||
VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=foo_agenda)
|
||||
VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=bar_agenda)
|
||||
output = get_output_of_command('export_site')
|
||||
payload = json.loads(output)
|
||||
assert len(payload['agendas']) == 3
|
||||
virtual_agenda.delete()
|
||||
foo_agenda.delete()
|
||||
bar_agenda.delete()
|
||||
mt1.delete()
|
||||
mt2.delete()
|
||||
import_site(payload, overwrite=True)
|
||||
|
||||
virtual_agenda = Agenda.objects.get(label='Virtual Agenda', slug='virtual-agenda', kind='virtual')
|
||||
assert virtual_agenda.real_agendas.count() == 2
|
||||
assert virtual_agenda.real_agendas.filter(label='Foo').count() == 1
|
||||
assert virtual_agenda.real_agendas.filter(label='Bar').count() == 1
|
||||
|
||||
# add incompatible meetingtype
|
||||
bar_agenda = Agenda.objects.get(label='Bar', kind='meetings')
|
||||
mt2 = MeetingType.objects.get(agenda=bar_agenda, label='Meeting Type')
|
||||
mt2.duration = 10
|
||||
mt2.save()
|
||||
output = get_output_of_command('export_site')
|
||||
payload = json.loads(output)
|
||||
virtual_agenda.delete()
|
||||
with pytest.raises(AgendaImportError) as excinfo:
|
||||
import_site(json.loads(output), overwrite=False)
|
||||
assert (
|
||||
'This agenda does not have the same meeting types provided by the virtual agenda.'
|
||||
in '%s' % excinfo.value
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue