Projet

Général

Profil

0001-virtual-agendas-handle-import-export-40057.patch

Emmanuel Cazenave, 17 mars 2020 13:31

Télécharger (8,42 ko)

Voir les différences:

Subject: [PATCH] virtual agendas: handle import/export (#40057)

 chrono/agendas/models.py    | 23 +++++++++
 chrono/manager/utils.py     |  7 ++-
 tests/test_import_export.py | 99 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 127 insertions(+), 2 deletions(-)
chrono/agendas/models.py
216 216
        elif self.kind == 'meetings':
217 217
            agenda['meetingtypes'] = [x.export_json() for x in self.meetingtype_set.all()]
218 218
            agenda['desks'] = [desk.export_json() for desk in self.desk_set.all()]
219
        elif self.kind == 'virtual':
220
            agenda['excluded_timeperiods'] = [x.export_json() for x in self.excluded_timeperiods.all()]
221
            agenda['real_agendas'] = [{'slug': x.slug, 'kind': x.kind} for x in self.real_agendas.all()]
219 222
        return agenda
220 223

  
221 224
    @classmethod
......
227 230
        elif data['kind'] == 'meetings':
228 231
            meetingtypes = data.pop('meetingtypes')
229 232
            desks = data.pop('desks')
233
        elif data['kind'] == 'virtual':
234
            excluded_timeperiods = data.pop('excluded_timeperiods')
235
            real_agendas = data.pop('real_agendas')
230 236
        for permission in ('view', 'edit'):
231 237
            if permissions.get(permission):
232 238
                try:
......
253 259
            for desk in desks:
254 260
                desk['agenda'] = agenda
255 261
                Desk.import_json(desk).save()
262
        elif data['kind'] == 'virtual':
263
            if overwrite:
264
                TimePeriod.objects.filter(agenda=agenda).delete()
265
                VirtualMember.objects.filter(virtual_agenda=agenda).delete()
266
            for excluded_timeperiod in excluded_timeperiods:
267
                excluded_timeperiod['agenda'] = agenda
268
                TimePeriod.import_json(excluded_timeperiod).save()
269
            for real_agenda in real_agendas:
270
                real_agenda = Agenda.objects.get(slug=real_agenda['slug'], kind=real_agenda['kind'])
271
                try:
272
                    vm, created = VirtualMember.objects.get_or_create(
273
                        virtual_agenda=agenda, real_agenda=real_agenda
274
                    )
275
                    vm.clean()
276
                except ValidationError as e:
277
                    raise AgendaImportError(e.message)
278

  
256 279
        return created
257 280

  
258 281

  
chrono/manager/utils.py
14 14
# You should have received a copy of the GNU Affero General Public License
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17
import itertools
18

  
17 19
from django.db import transaction
20
from django.db.models import Q
18 21

  
19 22
from chrono.agendas.models import Agenda, AgendaImportError
20 23

  
......
22 25
def export_site():
23 26
    '''Dump site objects to JSON-dumpable dictionnary'''
24 27
    data = {}
25
    data['agendas'] = [x.export_json() for x in Agenda.objects.all()]
28
    qs1 = Agenda.objects.filter(~Q(kind='virtual'))
29
    qs2 = Agenda.objects.filter(kind='virtual')
30
    data['agendas'] = [x.export_json() for x in itertools.chain(qs1, qs2)]
26 31
    return data
27 32

  
28 33

  
tests/test_import_export.py
16 16
from django.utils.encoding import force_bytes
17 17
from django.utils.timezone import make_aware
18 18

  
19
from chrono.agendas.models import Agenda, Event, TimePeriod, Desk, TimePeriodException, AgendaImportError
19
from chrono.agendas.models import (
20
    Agenda,
21
    Event,
22
    TimePeriod,
23
    Desk,
24
    TimePeriodException,
25
    AgendaImportError,
26
    MeetingType,
27
    VirtualMember,
28
)
20 29
from chrono.manager.utils import import_site
21 30

  
22 31
from test_api import some_data, meetings_agenda, time_zone, mock_now
......
179 188
    agenda = Agenda.objects.get(slug=meetings_agenda.slug)
180 189
    assert agenda.view_role == group1
181 190
    assert agenda.edit_role == group2
191

  
192

  
193
def test_import_export_virtual_agenda(app):
194
    virtual_agenda = Agenda.objects.create(label='Virtual Agenda', kind='virtual')
195
    output = get_output_of_command('export_site')
196
    payload = json.loads(output)
197
    assert len(payload['agendas']) == 1
198
    virtual_agenda.delete()
199
    import_site(json.loads(output), overwrite=True)
200

  
201
    virtual_agenda = Agenda.objects.get(label='Virtual Agenda', slug='virtual-agenda', kind='virtual')
202
    assert virtual_agenda.minimal_booking_delay is None
203
    assert virtual_agenda.maximal_booking_delay is None
204
    assert virtual_agenda.real_agendas.count() == 0
205
    assert virtual_agenda.excluded_timeperiods.count() == 0
206

  
207
    # add booking delay
208
    virtual_agenda.minimal_booking_delay = 2
209
    virtual_agenda.maximal_booking_delay = 10
210
    virtual_agenda.save()
211
    output = get_output_of_command('export_site')
212
    payload = json.loads(output)
213
    virtual_agenda.delete()
214
    import_site(json.loads(output), overwrite=True)
215
    virtual_agenda = Agenda.objects.get(label='Virtual Agenda', slug='virtual-agenda', kind='virtual')
216
    assert virtual_agenda.minimal_booking_delay == 2
217
    assert virtual_agenda.maximal_booking_delay == 10
218

  
219
    # add excluded timeperiods
220
    tp1 = TimePeriod.objects.create(
221
        agenda=virtual_agenda, weekday=1, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
222
    )
223
    tp2 = TimePeriod.objects.create(
224
        agenda=virtual_agenda, weekday=2, start_time=datetime.time(12, 0), end_time=datetime.time(13, 0)
225
    )
226
    output = get_output_of_command('export_site')
227
    payload = json.loads(output)
228
    virtual_agenda.delete()
229
    tp1.delete()
230
    tp2.delete()
231
    import_site(json.loads(output), overwrite=True)
232
    virtual_agenda = Agenda.objects.get(label='Virtual Agenda', slug='virtual-agenda', kind='virtual')
233
    assert virtual_agenda.excluded_timeperiods.count() == 2
234
    tp1 = TimePeriod.objects.get(
235
        agenda=virtual_agenda, weekday=1, start_time=datetime.time(10, 0), end_time=datetime.time(11, 0)
236
    )
237
    tp2 = TimePeriod.objects.get(
238
        agenda=virtual_agenda, weekday=2, start_time=datetime.time(12, 0), end_time=datetime.time(13, 0)
239
    )
240

  
241

  
242
def test_import_export_virtual_agenda_with_included_agenda(app):
243
    virtual_agenda = Agenda.objects.create(label='Virtual Agenda', kind='virtual')
244
    foo_agenda = Agenda.objects.create(label='Foo', kind='meetings')
245
    bar_agenda = Agenda.objects.create(label='Bar', kind='meetings')
246
    mt1 = MeetingType.objects.create(agenda=foo_agenda, label='Meeting Type', duration=30)
247
    mt2 = MeetingType.objects.create(agenda=bar_agenda, label='Meeting Type', duration=30)
248
    VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=foo_agenda)
249
    VirtualMember.objects.create(virtual_agenda=virtual_agenda, real_agenda=bar_agenda)
250
    output = get_output_of_command('export_site')
251
    payload = json.loads(output)
252
    assert len(payload['agendas']) == 3
253
    virtual_agenda.delete()
254
    foo_agenda.delete()
255
    bar_agenda.delete()
256
    mt1.delete()
257
    mt2.delete()
258
    import_site(payload, overwrite=True)
259

  
260
    virtual_agenda = Agenda.objects.get(label='Virtual Agenda', slug='virtual-agenda', kind='virtual')
261
    assert virtual_agenda.real_agendas.count() == 2
262
    assert virtual_agenda.real_agendas.filter(label='Foo').count() == 1
263
    assert virtual_agenda.real_agendas.filter(label='Bar').count() == 1
264

  
265
    # add incompatible meetingtype
266
    bar_agenda = Agenda.objects.get(label='Bar', kind='meetings')
267
    mt2 = MeetingType.objects.get(agenda=bar_agenda, label='Meeting Type')
268
    mt2.duration = 10
269
    mt2.save()
270
    output = get_output_of_command('export_site')
271
    payload = json.loads(output)
272
    virtual_agenda.delete()
273
    with pytest.raises(AgendaImportError) as excinfo:
274
        import_site(json.loads(output), overwrite=False)
275
    assert (
276
        '%s' % excinfo.value
277
        == 'This agenda does not have the same meetingtypes provided by the virtual agenda.'
278
    )
182
-