api: add new filters to get overlapping subscriptions (#71579) #9
|
@ -2251,8 +2251,8 @@ agendas_events_check_status = MultipleAgendasEventsCheckStatus.as_view()
|
|||
|
||||
|
||||
class SubscriptionFilter(filters.FilterSet):
|
||||
date_start = filters.DateFilter(lookup_expr='gte')
|
||||
date_end = filters.DateFilter(lookup_expr='lt')
|
||||
date_start = filters.DateFilter(method='do_nothing')
|
||||
date_end = filters.DateFilter(method='do_nothing')
|
||||
|
||||
class Meta:
|
||||
lguerin marked this conversation as resolved
Outdated
|
||||
model = Subscription
|
||||
|
@ -2262,6 +2262,28 @@ class SubscriptionFilter(filters.FilterSet):
|
|||
'date_end',
|
||||
]
|
||||
|
||||
def do_nothing(self, queryset, name, value):
|
||||
return queryset
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
queryset = super().filter_queryset(queryset)
|
||||
overlaps = {k: self.form.cleaned_data[k] for k in ['date_start', 'date_end']}
|
||||
if any(overlaps.values()):
|
||||
if not all(overlaps.values()):
|
||||
missing = [k for k, v in overlaps.items() if not v][0]
|
||||
not_missing = [k for k, v in overlaps.items() if v][0]
|
||||
raise ValidationError(
|
||||
{missing: _('This filter is required when using "%s" filter.') % not_missing}
|
||||
vdeniaud marked this conversation as resolved
vdeniaud
commented
J'ai l'impression qu'il y a moyen de déléguer la validation de filtres dépendants l'un de l'autre à django-filters https://rpkilby.github.io/django-filter/guide/usage.html#process-filters-together-with-meta-groups. J'ai l'impression qu'il y a moyen de déléguer la validation de filtres dépendants l'un de l'autre à django-filters https://rpkilby.github.io/django-filter/guide/usage.html#process-filters-together-with-meta-groups.
lguerin
commented
Ca aurait été bien, mais je ne trouve pas les groups dans le code ni dans la doc officielle: https://django-filter.readthedocs.io/en/main/guide/usage.html#the-filter Ca aurait été bien, mais je ne trouve pas les groups dans le code ni dans la doc officielle: https://django-filter.readthedocs.io/en/main/guide/usage.html#the-filter
vdeniaud
commented
Zut j'ai pas vérifié que c'était la doc officielle, c'est la faute à Google ! Zut j'ai pas vérifié que c'était la doc officielle, c'est la faute à Google !
|
||||
)
|
||||
queryset = queryset.extra(
|
||||
where=["(date_start, date_end) OVERLAPS (%s, %s)"],
|
||||
params=[
|
||||
self.form.cleaned_data['date_start'],
|
||||
self.form.cleaned_data['date_end'],
|
||||
],
|
||||
)
|
||||
return queryset
|
||||
|
||||
|
||||
class SubscriptionsAPI(ListAPIView):
|
||||
filter_backends = (filters.DjangoFilterBackend,)
|
||||
|
|
|
@ -75,7 +75,7 @@ def test_api_list_subscription_filter_user_external_id(app, user):
|
|||
assert [d['id'] for d in resp.json['data']] == []
|
||||
|
||||
|
||||
def test_api_list_subscription_filter_date_start(app, user):
|
||||
def test_api_list_subscription_filter_date_overlaps(app, user):
|
||||
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
||||
subscription1 = Subscription.objects.create(
|
||||
agenda=agenda,
|
||||
|
@ -92,47 +92,59 @@ def test_api_list_subscription_filter_date_start(app, user):
|
|||
|
||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||
|
||||
resp = app.get('/api/agenda/%s/subscription/' % agenda.slug, params={'date_start': '2021-09-01'})
|
||||
assert [d['id'] for d in resp.json['data']] == [subscription1.pk, subscription2.pk]
|
||||
resp = app.get('/api/agenda/%s/subscription/' % agenda.slug, params={'date_start': '2021-09-02'})
|
||||
assert [d['id'] for d in resp.json['data']] == [subscription2.pk]
|
||||
resp = app.get('/api/agenda/%s/subscription/' % agenda.slug, params={'date_start': '2022-09-02'})
|
||||
assert [d['id'] for d in resp.json['data']] == []
|
||||
|
||||
resp = app.get(
|
||||
'/api/agenda/%s/subscription/' % agenda.slug, params={'date_start': 'wrong-format'}, status=400
|
||||
'/api/agenda/%s/subscription/' % agenda.slug,
|
||||
params={'date_start': '2021-08-31', 'date_end': '2021-09-01'},
|
||||
)
|
||||
assert resp.json['err_class'] == 'invalid filters'
|
||||
|
||||
|
||||
def test_api_list_subscription_filter_date_end(app, user):
|
||||
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
||||
subscription1 = Subscription.objects.create(
|
||||
agenda=agenda,
|
||||
user_external_id='xxx',
|
||||
date_start=datetime.date(year=2021, month=9, day=1),
|
||||
date_end=datetime.date(year=2021, month=10, day=1),
|
||||
assert [d['id'] for d in resp.json['data']] == []
|
||||
resp = app.get(
|
||||
'/api/agenda/%s/subscription/' % agenda.slug,
|
||||
params={'date_start': '2021-08-31', 'date_end': '2021-09-02'},
|
||||
)
|
||||
subscription2 = Subscription.objects.create(
|
||||
agenda=agenda,
|
||||
user_external_id='xxx',
|
||||
date_start=datetime.date(year=2022, month=9, day=1),
|
||||
date_end=datetime.date(year=2022, month=10, day=1),
|
||||
)
|
||||
|
||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||
|
||||
resp = app.get('/api/agenda/%s/subscription/' % agenda.slug, params={'date_end': '2022-10-02'})
|
||||
assert [d['id'] for d in resp.json['data']] == [subscription1.pk, subscription2.pk]
|
||||
resp = app.get('/api/agenda/%s/subscription/' % agenda.slug, params={'date_end': '2021-10-02'})
|
||||
assert [d['id'] for d in resp.json['data']] == [subscription1.pk]
|
||||
resp = app.get('/api/agenda/%s/subscription/' % agenda.slug, params={'date_end': '2021-10-01'})
|
||||
resp = app.get(
|
||||
'/api/agenda/%s/subscription/' % agenda.slug,
|
||||
params={'date_start': '2021-09-02', 'date_end': '2021-09-30'},
|
||||
)
|
||||
assert [d['id'] for d in resp.json['data']] == [subscription1.pk]
|
||||
resp = app.get(
|
||||
'/api/agenda/%s/subscription/' % agenda.slug,
|
||||
params={'date_start': '2021-09-30', 'date_end': '2021-10-01'},
|
||||
)
|
||||
assert [d['id'] for d in resp.json['data']] == [subscription1.pk]
|
||||
resp = app.get(
|
||||
'/api/agenda/%s/subscription/' % agenda.slug,
|
||||
params={'date_start': '2021-10-01', 'date_end': '2021-10-02'},
|
||||
)
|
||||
assert [d['id'] for d in resp.json['data']] == []
|
||||
resp = app.get(
|
||||
'/api/agenda/%s/subscription/' % agenda.slug,
|
||||
params={'date_start': '2021-09-15', 'date_end': '2022-09-15'},
|
||||
)
|
||||
assert [d['id'] for d in resp.json['data']] == [subscription1.pk, subscription2.pk]
|
||||
|
||||
resp = app.get(
|
||||
'/api/agenda/%s/subscription/' % agenda.slug, params={'date_end': 'wrong-format'}, status=400
|
||||
'/api/agenda/%s/subscription/' % agenda.slug,
|
||||
params={'date_start': 'wrong-format', 'date_end': '2021-09-01'},
|
||||
status=400,
|
||||
)
|
||||
assert resp.json['err_class'] == 'invalid filters'
|
||||
resp = app.get(
|
||||
'/api/agenda/%s/subscription/' % agenda.slug,
|
||||
params={'date_start': '2021-08-31', 'date_end': 'wrong-format'},
|
||||
status=400,
|
||||
)
|
||||
assert resp.json['err_class'] == 'invalid filters'
|
||||
resp = app.get(
|
||||
'/api/agenda/%s/subscription/' % agenda.slug, params={'date_start': '2021-08-31'}, status=400
|
||||
)
|
||||
assert resp.json['err_class'] == 'invalid filters'
|
||||
assert resp.json['errors']['date_end'] == 'This filter is required when using "date_start" filter.'
|
||||
resp = app.get(
|
||||
'/api/agenda/%s/subscription/' % agenda.slug, params={'date_end': '2021-09-01'}, status=400
|
||||
)
|
||||
assert resp.json['err_class'] == 'invalid filters'
|
||||
assert resp.json['errors']['date_start'] == 'This filter is required when using "date_end" filter.'
|
||||
|
||||
|
||||
def test_api_create_subscription(app, user):
|
||||
|
|
Loading…
Reference in New Issue
Pas super convaincue par l'ajout de nouveaux filtres date_xx_overlaps.
Plutôt changer le comportement des filtres date_start et date_end existants ?
Si on n'a rien qui les utilise, oui pour changer le comportement.
OK, ce n'est pas utilisé dans publik-famille, on va dire que ce n'est pas utilisé.