diff --git a/chrono/agendas/migrations/0101_publication_datetime.py b/chrono/agendas/migrations/0101_publication_datetime.py new file mode 100644 index 00000000..5c23e46a --- /dev/null +++ b/chrono/agendas/migrations/0101_publication_datetime.py @@ -0,0 +1,16 @@ +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('agendas', '0100_event_dml'), + ] + + operations = [ + migrations.AddField( + model_name='event', + name='publication_datetime', + field=models.DateTimeField(blank=True, null=True, verbose_name='Publication date/time'), + ), + ] diff --git a/chrono/agendas/migrations/0102_publication_datetime.py b/chrono/agendas/migrations/0102_publication_datetime.py new file mode 100644 index 00000000..db03d452 --- /dev/null +++ b/chrono/agendas/migrations/0102_publication_datetime.py @@ -0,0 +1,31 @@ +import datetime + +from django.db import migrations +from django.utils.timezone import localtime, make_aware + + +def forwards(apps, schema_editor): + Event = apps.get_model('agendas', 'Event') + for event in Event.objects.filter(publication_date__isnull=False): + event.publication_datetime = make_aware( + datetime.datetime.combine(event.publication_date, datetime.time(0, 0)) + ) + event.save() + + +def backwards(apps, schema_editor): + Event = apps.get_model('agendas', 'Event') + for event in Event.objects.filter(publication_datetime__isnull=False): + event.publication_date = localtime(event.publication_datetime).date() + event.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('agendas', '0101_publication_datetime'), + ] + + operations = [ + migrations.RunPython(forwards, reverse_code=backwards), + ] diff --git a/chrono/agendas/migrations/0103_publication_datetime.py b/chrono/agendas/migrations/0103_publication_datetime.py new file mode 100644 index 00000000..d5a3915b --- /dev/null +++ b/chrono/agendas/migrations/0103_publication_datetime.py @@ -0,0 +1,15 @@ +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('agendas', '0102_publication_datetime'), + ] + + operations = [ + migrations.RemoveField( + model_name='event', + name='publication_date', + ), + ] diff --git a/chrono/agendas/models.py b/chrono/agendas/models.py index f0e97f34..df541279 100644 --- a/chrono/agendas/models.py +++ b/chrono/agendas/models.py @@ -133,7 +133,7 @@ def django_template_validator(value): def event_template_validator(value): example_event = Event( start_datetime=now(), - publication_date=now().date(), + publication_datetime=now(), recurrence_end_date=now().date(), places=1, duration=1, @@ -666,7 +666,7 @@ class Agenda(models.Model): entries = entries.filter(start_datetime__gte=localtime(now())) # exclude non published events entries = entries.filter( - Q(publication_date__isnull=True) | Q(publication_date__lte=localtime(now()).date()) + Q(publication_datetime__isnull=True) | Q(publication_datetime__lte=now()) ) if not include_full: entries = entries.filter(Q(full=False) | Q(primary_event__isnull=False)) @@ -745,7 +745,7 @@ class Agenda(models.Model): def get_open_recurring_events(self): return self.event_set.filter( - Q(publication_date__isnull=True) | Q(publication_date__lte=localtime(now()).date()), + Q(publication_datetime__isnull=True) | Q(publication_datetime__lte=now()), recurrence_days__isnull=False, recurrence_end_date__gt=localtime(now()).date(), ) @@ -773,7 +773,7 @@ class Agenda(models.Model): exceptions = self.prefetched_exceptions else: recurring_events = self.event_set.filter( - Q(publication_date__isnull=True) | Q(publication_date__lte=localtime(now()).date()), + Q(publication_datetime__isnull=True) | Q(publication_datetime__lte=now()), recurrence_days__isnull=False, ) exceptions = self.get_recurrence_exceptions(min_start, max_start) @@ -884,7 +884,7 @@ class Agenda(models.Model): qs, user_external_id=None, show_past_events=False, min_start=None, max_start=None ): event_queryset = Event.objects.filter( - Q(publication_date__isnull=True) | Q(publication_date__lte=localtime(now()).date()), + Q(publication_datetime__isnull=True) | Q(publication_datetime__lte=now()), recurrence_days__isnull=True, cancelled=False, ).order_by() @@ -899,7 +899,7 @@ class Agenda(models.Model): event_queryset = event_queryset.filter(start_datetime__lt=max_start) recurring_event_queryset = Event.objects.filter( - Q(publication_date__isnull=True) | Q(publication_date__lte=localtime(now()).date()), + Q(publication_datetime__isnull=True) | Q(publication_datetime__lte=now()), recurrence_days__isnull=False, ) exceptions_desk = Desk.objects.filter(slug='_exceptions_holder').prefetch_related( @@ -1355,7 +1355,7 @@ class Event(models.Model): recurrence_end_date = models.DateField(_('Recurrence end date'), null=True, blank=True) primary_event = models.ForeignKey('self', null=True, on_delete=models.CASCADE, related_name='recurrences') duration = models.PositiveIntegerField(_('Duration (in minutes)'), default=None, null=True, blank=True) - publication_date = models.DateField(_('Publication date'), blank=True, null=True) + publication_datetime = models.DateTimeField(_('Publication date/time'), blank=True, null=True) places = models.PositiveIntegerField(_('Places')) waiting_list_places = models.PositiveIntegerField(_('Places in waiting list'), default=0) label = models.CharField( @@ -1451,7 +1451,7 @@ class Event(models.Model): self.save(update_fields=['checked']) def in_bookable_period(self): - if self.publication_date and localtime(now()).date() < self.publication_date: + if self.publication_datetime and now() < self.publication_datetime: return False if self.agenda.maximal_booking_delay and self.start_datetime > self.agenda.max_booking_datetime: return False @@ -1545,7 +1545,7 @@ class Event(models.Model): for field in [ 'label', 'duration', - 'publication_date', + 'publication_datetime', 'places', 'waiting_list_places', 'description', @@ -1565,7 +1565,9 @@ class Event(models.Model): ) return { 'start_datetime': make_naive(self.start_datetime).strftime('%Y-%m-%d %H:%M:%S'), - 'publication_date': self.publication_date.strftime('%Y-%m-%d') if self.publication_date else None, + 'publication_datetime': make_naive(self.publication_datetime).strftime('%Y-%m-%d %H:%M:%S') + if self.publication_datetime + else None, 'recurrence_days': self.recurrence_days, 'recurrence_week_interval': self.recurrence_week_interval, 'recurrence_end_date': recurrence_end_date, @@ -1659,7 +1661,7 @@ class Event(models.Model): duration=self.duration, places=self.places, waiting_list_places=self.waiting_list_places, - publication_date=self.publication_date, + publication_datetime=self.publication_datetime, label=self.label, description=self.description, pricing=self.pricing, diff --git a/chrono/api/serializers.py b/chrono/api/serializers.py index 198d9eb0..c3783131 100644 --- a/chrono/api/serializers.py +++ b/chrono/api/serializers.py @@ -150,7 +150,7 @@ class EventSerializer(serializers.ModelSerializer): 'recurrence_week_interval', 'recurrence_end_date', 'duration', - 'publication_date', + 'publication_datetime', 'places', 'waiting_list_places', 'label', diff --git a/chrono/api/views.py b/chrono/api/views.py index 5f6e4da8..e60a7991 100644 --- a/chrono/api/views.py +++ b/chrono/api/views.py @@ -2260,7 +2260,7 @@ class Events(APIView): for field in changed_data: if field in ( 'recurrence_end_date', - 'publication_date', + 'publication_datetime', 'recurrence_days', 'recurrence_week_interval', ): diff --git a/chrono/manager/forms.py b/chrono/manager/forms.py index abdbb989..ae7b04e9 100644 --- a/chrono/manager/forms.py +++ b/chrono/manager/forms.py @@ -216,7 +216,6 @@ class EventForm(NewEventForm): class Meta: model = Event widgets = { - 'publication_date': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'), 'recurrence_end_date': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'), } fields = [ @@ -228,7 +227,7 @@ class EventForm(NewEventForm): 'recurrence_week_interval', 'recurrence_end_date', 'duration', - 'publication_date', + 'publication_datetime', 'places', 'waiting_list_places', 'description', @@ -237,6 +236,7 @@ class EventForm(NewEventForm): ] field_classes = { 'start_datetime': SplitDateTimeField, + 'publication_datetime': SplitDateTimeField, } def __init__(self, *args, **kwargs): @@ -252,7 +252,7 @@ class EventForm(NewEventForm): for field in ( 'slug', 'recurrence_end_date', - 'publication_date', + 'publication_datetime', 'frequency', 'recurrence_days', 'recurrence_week_interval', @@ -706,14 +706,24 @@ class ImportEventsForm(forms.Form): column_index += 1 if len(csvline) >= 10 and csvline[9]: # publication date is optional - for date_fmt in ('%Y-%m-%d', '%d/%m/%Y'): + for datetime_fmt in ( + '%Y-%m-%d', + '%d/%m/%Y', + '%Y-%m-%d %H:%M', + '%d/%m/%Y %H:%M', + '%d/%m/%Y %Hh%M', + '%Y-%m-%d %H:%M:%S', + '%d/%m/%Y %H:%M:%S', + ): try: - event.publication_date = datetime.datetime.strptime(csvline[9], date_fmt).date() + event.publication_datetime = make_aware( + datetime.datetime.strptime(csvline[9], datetime_fmt) + ) break except ValueError: continue else: - raise ValidationError(_('Invalid file format. (date format, line %d)') % (i + 1)) + raise ValidationError(_('Invalid file format. (date/time format, line %d)') % (i + 1)) if len(csvline) >= 11 and csvline[10]: # duration is optional try: diff --git a/chrono/manager/templates/chrono/manager_agenda_event_fragment.html b/chrono/manager/templates/chrono/manager_agenda_event_fragment.html index f832427f..5b65db9e 100644 --- a/chrono/manager/templates/chrono/manager_agenda_event_fragment.html +++ b/chrono/manager/templates/chrono/manager_agenda_event_fragment.html @@ -43,8 +43,8 @@ {% blocktrans with places=event.waiting_list_places count booked_places=event.booked_waiting_list_places %}{{ booked_places }}/{{ places }} booking{% plural %}{{ booked_places }}/{{ places }} bookings{% endblocktrans %}) {% endif %} {% endif %} - {% if view_mode == 'settings_view' and event.publication_date %} - ({% trans "publication date:" %} {{ event.publication_date }}) + {% if view_mode == 'settings_view' and event.publication_datetime %} + ({% trans "publication date:" %} {{ event.publication_datetime }}) {% endif %} {% if not event.in_bookable_period %} ({% trans "out of bookable period" %}) diff --git a/chrono/manager/templates/chrono/manager_event_detail_fragment.html b/chrono/manager/templates/chrono/manager_event_detail_fragment.html index 82fc7925..5803b2cb 100644 --- a/chrono/manager/templates/chrono/manager_event_detail_fragment.html +++ b/chrono/manager/templates/chrono/manager_event_detail_fragment.html @@ -5,7 +5,7 @@ {% if object.description %}{{ object.description|linebreaks }}{% endif %} {% if object.pricing %}

{% trans "Pricing:" %} {{ object.pricing }}

{% endif %} {% if object.url %}

{{ object.url|truncatechars:100 }}

{% endif %} - {% if object.publication_date %}

{% trans "Publication date:" %} {{ object.publication_date }}

{% endif %} + {% if object.publication_datetime %}

{% trans "Publication date:" %} {{ object.publication_datetime }}

{% endif %} {% endif %} diff --git a/chrono/manager/templates/chrono/manager_sample_events.txt b/chrono/manager/templates/chrono/manager_sample_events.txt index 180fe266..373e5949 100644 --- a/chrono/manager/templates/chrono/manager_sample_events.txt +++ b/chrono/manager/templates/chrono/manager_sample_events.txt @@ -1,2 +1,2 @@ -{% load i18n %}{% trans 'date' %},{% trans 'time' %},{% trans 'number of places' %},{% trans 'number of places in waiting list' %},{% trans 'label' %},{% trans 'identifier' %},{% trans 'description' %},{% trans 'pricing' %},{% trans 'URL' %},{% trans 'publication date' %},{% trans 'duration' %} -{{ some_future_date|date:"Y-m-d" }},{{ some_future_date|date:"H:i" }},15,0,{% trans "example event" as label %}{{ label }},{{ label|slugify }},,,https://www.example.net,{{ some_future_date|date:"Y-m-d" }},30 +{% load i18n %}{% trans 'date' %},{% trans 'time' %},{% trans 'number of places' %},{% trans 'number of places in waiting list' %},{% trans 'label' %},{% trans 'identifier' %},{% trans 'description' %},{% trans 'pricing' %},{% trans 'URL' %},{% trans 'publication date/time' %},{% trans 'duration' %} +{{ some_future_date|date:"Y-m-d" }},{{ some_future_date|date:"H:i" }},15,0,{% trans "example event" as label %}{{ label }},{{ label|slugify }},,,https://www.example.net,{{ some_future_date|date:"Y-m-d H:i" }},30 diff --git a/chrono/manager/views.py b/chrono/manager/views.py index ad0eae4c..defafe1f 100644 --- a/chrono/manager/views.py +++ b/chrono/manager/views.py @@ -1804,12 +1804,15 @@ class AgendaExportEventsView(ManagedAgendaMixin, View): _('description'), _('pricing'), _('URL'), - _('publication date'), + _('publication date/time'), _('duration'), ] ) for event in self.agenda.event_set.all(): start_datetime = localtime(event.start_datetime) + publication_datetime = ( + localtime(event.publication_datetime) if event.publication_datetime else None + ) writer.writerow( [ start_datetime.strftime('%Y-%m-%d'), @@ -1821,7 +1824,7 @@ class AgendaExportEventsView(ManagedAgendaMixin, View): event.description, event.pricing, event.url, - event.publication_date.strftime('%Y-%m-%d') if event.publication_date else '', + publication_datetime.strftime('%Y-%m-%d %H:%M') if publication_datetime else '', event.duration, ] ) diff --git a/tests/api/test_all.py b/tests/api/test_all.py index ef24a2ae..2a111462 100644 --- a/tests/api/test_all.py +++ b/tests/api/test_all.py @@ -261,7 +261,7 @@ def test_agendas_api(app): event2.booking_set.all().delete() event2.refresh_from_db() assert event2.full is False - event_agenda.event_set.update(publication_date=now().date() + datetime.timedelta(days=20)) + event_agenda.event_set.update(publication_datetime=now() + datetime.timedelta(days=20)) assert list(event_agenda.get_open_events()) == [] resp = app.get('/api/agenda/', params={'with_open_events': '1'}) assert len(resp.json['data']) == 0 @@ -476,7 +476,7 @@ def test_agenda_detail_api(app): event2.booking_set.all().delete() event2.refresh_from_db() assert event2.full is False - agenda.event_set.update(publication_date=now().date() + datetime.timedelta(days=20)) + agenda.event_set.update(publication_datetime=now() + datetime.timedelta(days=20)) resp = app.get('/api/agenda/%s/' % agenda.slug) assert list(agenda.get_open_events()) == [] assert resp.json['data']['opened_events_available'] is False diff --git a/tests/api/test_datetimes.py b/tests/api/test_datetimes.py index 6d383862..9397d725 100644 --- a/tests/api/test_datetimes.py +++ b/tests/api/test_datetimes.py @@ -50,12 +50,12 @@ def test_datetimes_api(app, some_data): check_bookability(resp.json['data']) assert resp.json['data'][0]['description'] is None - agenda.event_set.update(publication_date=localtime(now()).date() + datetime.timedelta(days=1)) + agenda.event_set.update(publication_datetime=now() + datetime.timedelta(minutes=1)) resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug) assert len(resp.json['data']) == 0 check_bookability(resp.json['data']) - agenda.event_set.update(publication_date=localtime(now()).date()) + agenda.event_set.update(publication_datetime=now()) resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug) assert len(resp.json['data']) == 2 check_bookability(resp.json['data']) @@ -662,13 +662,13 @@ def test_recurring_events_api(app, user, freezer): # publication date is accounted for Event.objects.filter(primary_event=base_event).delete() - base_event.publication_date = now().replace(day=27) + base_event.publication_datetime = now().replace(day=27) base_event.save() resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug) assert len(resp.json['data']) == 0 # events follow agenda display template - Event.objects.all().update(publication_date=None) + Event.objects.all().update(publication_datetime=None) agenda.event_display_template = '{{ event.label }} - {{ event.start_datetime }}' agenda.save() resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug) @@ -677,7 +677,7 @@ def test_recurring_events_api(app, user, freezer): # check querysets agenda.event_display_template = '' agenda.save() - base_event.publication_date = None + base_event.publication_datetime = None base_event.recurrence_end_date = datetime.date.today() + datetime.timedelta(days=365) base_event.save() base_event.create_all_recurrences() @@ -1356,7 +1356,7 @@ def test_recurring_events_api_list(app, freezer): assert resp.json['data'][3]['id'] == 'other:1' assert resp.json['data'][3]['text'] == 'Tuesday: Other' - event.publication_date = now() + datetime.timedelta(days=2) + event.publication_datetime = now() + datetime.timedelta(days=2) event.save() resp = app.get('/api/agenda/%s/recurring-events/' % agenda.slug) assert len(resp.json['data']) == 1 diff --git a/tests/api/test_event.py b/tests/api/test_event.py index e0456c00..c552481b 100644 --- a/tests/api/test_event.py +++ b/tests/api/test_event.py @@ -224,13 +224,13 @@ def test_add_event(app, user): assert str(event.start_datetime) == '2021-11-15 14:38:00+00:00' assert str(event.start_datetime.tzinfo) == 'UTC' assert event.places == 10 - assert event.publication_date is None + assert event.publication_datetime is None # add with almost all optional managed fields params = { 'start_datetime': '2021-11-15 15:38', 'duration': 42, - 'publication_date': '2021-09-20', + 'publication_datetime': '2021-09-20 10:00', 'places': 11, 'waiting_list_places': 3, 'label': 'FOO camp', @@ -252,6 +252,8 @@ def test_add_event(app, user): assert event.description == 'An event' assert event.pricing == 'free' assert event.url == 'http://example.org/foo/bar/?' + assert str(event.publication_datetime) == '2021-09-20 08:00:00+00:00' + assert str(event.publication_datetime.tzinfo) == 'UTC' # add with errors in recurrence_days list params = { @@ -389,7 +391,7 @@ def test_update_event(app, user): params = { 'start_datetime': '2021-11-15 15:38', 'duration': 42, - 'publication_date': '2021-09-20', + 'publication_datetime': '2021-09-20 12:00', 'places': 8, 'waiting_list_places': 3, 'label': 'FOO camp', @@ -407,6 +409,8 @@ def test_update_event(app, user): assert event.description == 'An event' assert event.pricing == 'free' assert event.url == 'http://example.org/foo/bar/?' + assert str(event.publication_datetime) == '2021-09-20 10:00:00+00:00' + assert str(event.publication_datetime.tzinfo) == 'UTC' # update event as a recurring event params = { @@ -448,7 +452,7 @@ def test_update_event(app, user): # try to update protected fields of one of the event recurrencies params = { - 'publication_date': '2021-11-15', + 'publication_datetime': '2021-11-15 12:00', } resp = app.patch(recurrence_url, params=params, status=400) assert resp.json['err'] diff --git a/tests/manager/test_all.py b/tests/manager/test_all.py index 3fd52cc0..216acc9c 100644 --- a/tests/manager/test_all.py +++ b/tests/manager/test_all.py @@ -1553,7 +1553,7 @@ def test_agenda_open_events_view(app, admin_user, manager_user): agenda=agenda, label='event E', start_datetime=now() + datetime.timedelta(days=3), - publication_date=today + datetime.timedelta(days=1), + publication_datetime=now() + datetime.timedelta(days=1), places=42, ) # publication date in past @@ -1561,7 +1561,7 @@ def test_agenda_open_events_view(app, admin_user, manager_user): agenda=agenda, label='event F', start_datetime=now() + datetime.timedelta(days=3), - publication_date=today - datetime.timedelta(days=1), + publication_datetime=now() - datetime.timedelta(days=1), places=42, ) # weekly recurring event, first recurrence is in the past but second is in range @@ -1591,7 +1591,7 @@ def test_agenda_open_events_view(app, admin_user, manager_user): agenda=agenda, label='event H', start_datetime=now().replace(year=today.year + 2, month=1, day=15), - publication_date=today - datetime.timedelta(days=1), + publication_datetime=now() - datetime.timedelta(days=1), places=42, ) start_datetime = localtime(now().replace(year=today.year + 2, month=2, day=1)).replace(hour=0, minute=0) @@ -1599,7 +1599,7 @@ def test_agenda_open_events_view(app, admin_user, manager_user): agenda=agenda, label='event H', start_datetime=start_datetime, - publication_date=today - datetime.timedelta(days=1), + publication_datetime=now() - datetime.timedelta(days=1), places=42, ) resp = app.get('/manage/agendas/%s/events/open/' % agenda.pk) diff --git a/tests/manager/test_event.py b/tests/manager/test_event.py index b2274c33..ffa8afcb 100644 --- a/tests/manager/test_event.py +++ b/tests/manager/test_event.py @@ -33,7 +33,7 @@ def test_add_event(app, admin_user): resp = resp.form.submit() resp = resp.follow() event = Event.objects.get(places=10) - assert event.publication_date is None + assert event.publication_datetime is None assert "This agenda doesn't have any event yet." not in resp.text assert '/manage/agendas/%s/events/%s/' % (agenda.id, event.id) in resp.text assert ('Feb. 15, %s, 5 p.m.' % year) in resp.text @@ -137,12 +137,14 @@ def test_edit_event(settings, app, admin_user): resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.pk, event.pk)) assert resp.form['start_datetime_0'].value == '2016-02-15' assert resp.form['start_datetime_1'].value == '17:00' - assert resp.form['publication_date'].value == '' + assert resp.form['publication_datetime_0'].value == '' + assert resp.form['publication_datetime_1'].value == '' assert resp.form['duration'].value == '' assert resp.form['description'].value == '' resp.form['start_datetime_0'] = '2016-02-16' resp.form['start_datetime_1'] = '17:00' - resp.form['publication_date'] = '2020-05-11' + resp.form['publication_datetime_0'] = '2020-05-11' + resp.form['publication_datetime_1'] = '12:00' resp.form['duration'].value = 45 resp.form['places'] = 20 resp.form['description'] = 'A description' @@ -153,7 +155,8 @@ def test_edit_event(settings, app, admin_user): assert 'Feb. 16, 2016, 5 p.m.' in resp.text event.refresh_from_db() assert event.places == 20 - assert event.publication_date == datetime.date(2020, 5, 11) + assert str(event.publication_datetime) == '2020-05-11 10:00:00+00:00' + assert str(event.publication_datetime.tzinfo) == 'UTC' assert event.duration == 45 assert event.end_datetime == event.start_datetime + datetime.timedelta(minutes=45) assert event.description == 'A description' @@ -193,7 +196,7 @@ def test_edit_event_as_manager(app, manager_user): start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=20, agenda=agenda, - publication_date=datetime.date(2020, 5, 11), + publication_datetime=make_aware(datetime.datetime(2020, 5, 11)), ) app = login(app, username='manager', password='manager') resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id), status=403) @@ -204,17 +207,19 @@ def test_edit_event_as_manager(app, manager_user): resp = resp.click('Feb. 15, 2016, 5 p.m.') assert resp.form['start_datetime_0'].value == '2016-02-15' assert resp.form['start_datetime_1'].value == '17:00' - assert resp.form['publication_date'].value == '2020-05-11' + assert resp.form['publication_datetime_0'].value == '2020-05-11' + assert resp.form['publication_datetime_1'].value == '00:00' resp.form['start_datetime_0'] = '2016-02-16' resp.form['start_datetime_1'] = '17:00' - resp.form['publication_date'] = '' + resp.form['publication_datetime_0'] = '' + resp.form['publication_datetime_1'] = '' resp.form['places'] = 20 resp = resp.form.submit() resp = resp.follow() assert '/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id) in resp.text assert 'Feb. 16, 2016, 5 p.m.' in resp.text event.refresh_from_db() - assert event.publication_date is None + assert event.publication_datetime is None def test_edit_recurring_event(settings, app, admin_user, freezer): @@ -301,7 +306,8 @@ def test_edit_recurring_event(settings, app, admin_user, freezer): 'recurrence_days', 'recurence_weekly_interval', 'recurrence_end_date', - 'publication_date', + 'publication_datetime_0', + 'publication_datetime_1', }.isdisjoint(resp.form.fields) @@ -537,7 +543,7 @@ def test_export_events(app, admin_user): csv_export = resp.text assert ( csv_export - == 'date,time,number of places,number of places in waiting list,label,identifier,description,pricing,URL,publication date,duration\r\n' + == 'date,time,number of places,number of places in waiting list,label,identifier,description,pricing,URL,publication date/time,duration\r\n' ) resp = app.get('/manage/agendas/%s/import-events' % agenda.id) @@ -548,14 +554,14 @@ def test_export_events(app, admin_user): csv_export = resp.text assert ( csv_export - == 'date,time,number of places,number of places in waiting list,label,identifier,description,pricing,URL,publication date,duration\r\n' + == 'date,time,number of places,number of places in waiting list,label,identifier,description,pricing,URL,publication date/time,duration\r\n' '2016-09-16,00:30,10,0,,foo-bar-event,,,,,\r\n' ) resp = app.get('/manage/agendas/%s/import-events' % agenda.id) resp.form['events_csv_file'] = Upload( 't.csv', - b'2016-09-16,23:30,10,5,label,slug,"description\nfoobar",pricing,url,2016-10-16,90', + b'2016-09-16,23:30,10,5,label,slug,"description\nfoobar",pricing,url,2016-10-16 00:00,90', 'text/csv', ) resp.form.submit(status=302) @@ -563,9 +569,9 @@ def test_export_events(app, admin_user): csv_export = resp.text assert ( csv_export - == 'date,time,number of places,number of places in waiting list,label,identifier,description,pricing,URL,publication date,duration\r\n' + == 'date,time,number of places,number of places in waiting list,label,identifier,description,pricing,URL,publication date/time,duration\r\n' '2016-09-16,00:30,10,0,,foo-bar-event,,,,,\r\n' - '2016-09-16,23:30,10,5,label,slug,"description\nfoobar",pricing,url,2016-10-16,90\r\n' + '2016-09-16,23:30,10,5,label,slug,"description\nfoobar",pricing,url,2016-10-16 00:00,90\r\n' ) @@ -738,7 +744,7 @@ def test_import_events(app, admin_user): assert event.description == '' assert event.pricing == '' assert event.url == '' - assert event.publication_date is None + assert event.publication_datetime is None assert event.duration is None Event.objects.all().delete() resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200) @@ -753,16 +759,33 @@ def test_import_events(app, admin_user): assert event.description == 'description\nfoobar' assert event.pricing == 'pricing' assert event.url == 'url' - assert event.publication_date == datetime.date(2016, 10, 16) + assert str(event.publication_datetime) == '2016-10-15 22:00:00+00:00' + assert str(event.publication_datetime.tzinfo) == 'UTC' + assert event.duration == 90 + Event.objects.all().delete() + resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200) + resp.form['events_csv_file'] = Upload( + 't.csv', + b'2016-09-16,18:00,10,5,label,slug,"description\nfoobar",pricing,url,2016-10-16 10:00,90', + 'text/csv', + ) + resp = resp.form.submit(status=302) + assert Event.objects.count() == 1 + event = Event.objects.get() + assert event.description == 'description\nfoobar' + assert event.pricing == 'pricing' + assert event.url == 'url' + assert str(event.publication_datetime) == '2016-10-16 08:00:00+00:00' + assert str(event.publication_datetime.tzinfo) == 'UTC' assert event.duration == 90 - # publication date bad format + # publication date/time bad format resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200) resp.form['events_csv_file'] = Upload( 't.csv', b'2016-09-16,18:00,10,5,label,slug,description,pricing,url,foobar', 'text/csv' ) resp = resp.form.submit(status=200) - assert 'Invalid file format. (date format' in resp.text + assert 'Invalid file format. (date/time format' in resp.text # duration bad format resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200) diff --git a/tests/test_agendas.py b/tests/test_agendas.py index c33603ce..08666415 100644 --- a/tests/test_agendas.py +++ b/tests/test_agendas.py @@ -446,7 +446,7 @@ def test_event_manager(): [ # no delay (10, 0, 0, 0, None, True), - # test publication_date + # test publication_datetime (10, 0, 0, 0, 1, False), (10, 0, 0, 0, 0, True), # test min and max delays @@ -464,7 +464,7 @@ def test_event_bookable_period(start_days, start_minutes, min_delay, max_delay, ) event = Event.objects.create( start_datetime=localtime() + datetime.timedelta(days=start_days, minutes=start_minutes), - publication_date=(localtime().date() + datetime.timedelta(days=pub_days)) if pub_days else None, + publication_datetime=(localtime() + datetime.timedelta(days=pub_days)) if pub_days else None, places=10, agenda=agenda, ) diff --git a/tests/test_import_export.py b/tests/test_import_export.py index a6d3d5ea..a07ea2db 100644 --- a/tests/test_import_export.py +++ b/tests/test_import_export.py @@ -183,7 +183,7 @@ def test_import_export_event_details(app): description='description', pricing='100', url='https://example.net/', - publication_date=datetime.date(2020, 5, 11), + publication_datetime=make_aware(datetime.datetime(2020, 5, 11)), places=42, start_datetime=now(), duration=30, @@ -214,7 +214,8 @@ def test_import_export_event_details(app): assert first_imported_event.description == 'description' assert first_imported_event.pricing == '100' assert first_imported_event.url == 'https://example.net/' - assert first_imported_event.publication_date == datetime.date(2020, 5, 11) + assert str(first_imported_event.publication_datetime) == '2020-05-10 22:00:00+00:00' + assert str(first_imported_event.publication_datetime.tzinfo) == 'UTC' assert first_imported_event.duration == 30 assert Agenda.objects.get(label='Foo Bar 2').event_set.first().slug == 'event'