diff --git a/lingo/pricing/forms.py b/lingo/pricing/forms.py
index fba7ebb..d8a7061 100644
--- a/lingo/pricing/forms.py
+++ b/lingo/pricing/forms.py
@@ -187,6 +187,41 @@ class AgendaPricingForm(NewAgendaPricingForm):
)
return subscription_required
+ def clean(self):
+ cleaned_data = super().clean()
+ if (
+ 'date_start' in cleaned_data
+ and 'date_end' in cleaned_data
+ and 'flat_fee_schedule' in cleaned_data
+ ):
+ old_date_start = self.instance.date_start
+ old_date_end = self.instance.date_end
+ old_flat_fee_schedule = self.instance.flat_fee_schedule
+ new_date_start = cleaned_data['date_start']
+ new_date_end = cleaned_data['date_end']
+ new_flat_fee_schedule = cleaned_data['flat_fee_schedule']
+ if (
+ old_date_start != new_date_start
+ or old_date_end != new_date_end
+ or old_flat_fee_schedule != new_flat_fee_schedule
+ ):
+ overlapping_qs = (
+ AgendaPricing.objects.filter(flat_fee_schedule=new_flat_fee_schedule)
+ .exclude(pk=self.instance.pk)
+ .extra(
+ where=["(date_start, date_end) OVERLAPS (%s, %s)"],
+ params=[new_date_start, new_date_end],
+ )
+ )
+ for agenda in self.instance.agendas.all():
+ if overlapping_qs.filter(agendas=agenda).exists():
+ self.add_error(
+ None,
+ _('Agenda "%s" has already a pricing overlapping this period.') % agenda.label,
+ )
+
+ return cleaned_data
+
class AgendaPricingAgendaAddForm(forms.Form):
agenda = forms.ModelChoiceField(label=_('Agenda to add'), queryset=Agenda.objects.none(), required=True)
@@ -198,7 +233,9 @@ class AgendaPricingAgendaAddForm(forms.Form):
def clean_agenda(self):
agenda = self.cleaned_data['agenda']
- overlapping_qs = AgendaPricing.objects.filter(agendas=agenda).extra(
+ overlapping_qs = AgendaPricing.objects.filter(
+ flat_fee_schedule=self.agenda_pricing.flat_fee_schedule, agendas=agenda
+ ).extra(
where=["(date_start, date_end) OVERLAPS (%s, %s)"],
params=[self.agenda_pricing.date_start, self.agenda_pricing.date_end],
)
diff --git a/lingo/pricing/templates/lingo/pricing/manager_agenda_detail.html b/lingo/pricing/templates/lingo/pricing/manager_agenda_detail.html
index 662fb4c..af08741 100644
--- a/lingo/pricing/templates/lingo/pricing/manager_agenda_detail.html
+++ b/lingo/pricing/templates/lingo/pricing/manager_agenda_detail.html
@@ -26,6 +26,7 @@
+
{% trans "Pricings" context 'agenda pricing' %}
{% if agenda_pricings %}
{% for agenda_pricing in agenda_pricings %}
@@ -42,6 +43,23 @@
{% endblocktrans %}
{% endif %}
+
{% trans "Flat fee schedule pricings" %}
+ {% if agenda_pricings_flat %}
+
+ {% else %}
+
+ {% blocktrans %}
+ This agenda doesn't have any flat fee schedule pricing defined yet.
+ {% endblocktrans %}
+
+ {% endif %}
diff --git a/lingo/pricing/views.py b/lingo/pricing/views.py
index eef24ac..c72a219 100644
--- a/lingo/pricing/views.py
+++ b/lingo/pricing/views.py
@@ -683,7 +683,12 @@ class AgendaDetailView(AgendaMixin, DetailView):
def get_context_data(self, **kwargs):
kwargs['agenda_pricings'] = (
- AgendaPricing.objects.filter(agendas=self.agenda)
+ AgendaPricing.objects.filter(agendas=self.agenda, flat_fee_schedule=False)
+ .select_related('pricing')
+ .order_by('date_start', 'date_end')
+ )
+ kwargs['agenda_pricings_flat'] = (
+ AgendaPricing.objects.filter(agendas=self.agenda, flat_fee_schedule=True)
.select_related('pricing')
.order_by('date_start', 'date_end')
)
diff --git a/tests/pricing/manager/test_agenda_pricing.py b/tests/pricing/manager/test_agenda_pricing.py
index 87d178d..b48e73f 100644
--- a/tests/pricing/manager/test_agenda_pricing.py
+++ b/tests/pricing/manager/test_agenda_pricing.py
@@ -125,6 +125,144 @@ def test_edit_agenda_pricing(app, admin_user):
assert resp.location.endswith('/manage/pricing/agenda-pricing/%s/' % agenda_pricing.pk)
+def test_edit_agenda_pricing_overlapping_flat_fee_schedule(app, admin_user):
+ agenda1 = Agenda.objects.create(label='Foo bar 1')
+ agenda2 = Agenda.objects.create(label='Foo bar 2')
+ pricing = Pricing.objects.create(label='Model')
+ agenda_pricing1 = AgendaPricing.objects.create(
+ label='Foo Bar',
+ pricing=pricing,
+ date_start=datetime.date(year=2021, month=9, day=1),
+ date_end=datetime.date(year=2022, month=9, day=1),
+ )
+ agenda_pricing1.agendas.add(agenda1, agenda2)
+ agenda_pricing2 = AgendaPricing.objects.create(
+ label='Foo Bar',
+ pricing=pricing,
+ date_start=datetime.date(year=2021, month=9, day=1),
+ date_end=datetime.date(year=2022, month=9, day=1),
+ )
+ agenda_pricing2.agendas.add(agenda1, agenda2)
+
+ app = login(app)
+ resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
+ # ok, flat_fee_schedule has not changed
+ resp.form.submit().follow()
+
+ resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
+ # ok, flat_fee_schedule is different
+ resp.form['flat_fee_schedule'] = True
+ resp.form.submit().follow()
+
+ resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
+ resp.form['flat_fee_schedule'] = False
+ resp = resp.form.submit()
+ assert resp.context['form'].non_field_errors() == [
+ 'Agenda "Foo bar 1" has already a pricing overlapping this period.',
+ 'Agenda "Foo bar 2" has already a pricing overlapping this period.',
+ ]
+ agenda_pricing2.agendas.remove(agenda1)
+ resp = resp.form.submit()
+ assert resp.context['form'].non_field_errors() == [
+ 'Agenda "Foo bar 2" has already a pricing overlapping this period.'
+ ]
+ agenda_pricing2.agendas.remove(agenda2)
+ # ok
+ resp.form.submit().follow()
+
+
+def test_edit_agenda_pricing_overlapping_date_start(app, admin_user):
+ agenda1 = Agenda.objects.create(label='Foo bar 1')
+ agenda2 = Agenda.objects.create(label='Foo bar 2')
+ pricing = Pricing.objects.create(label='Model')
+ agenda_pricing1 = AgendaPricing.objects.create(
+ label='Foo Bar',
+ pricing=pricing,
+ date_start=datetime.date(year=2021, month=10, day=1),
+ date_end=datetime.date(year=2022, month=10, day=1),
+ )
+ agenda_pricing1.agendas.add(agenda1, agenda2)
+ agenda_pricing2 = AgendaPricing.objects.create(
+ label='Foo Bar',
+ pricing=pricing,
+ date_start=datetime.date(year=2021, month=9, day=1),
+ date_end=datetime.date(year=2022, month=9, day=1),
+ )
+ agenda_pricing2.agendas.add(agenda1, agenda2)
+
+ app = login(app)
+ resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
+ # ok, date_start has not changed
+ resp.form.submit().follow()
+
+ resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
+ # ok, no overlapping
+ resp.form['date_start'] = '2022-09-01'
+ resp.form.submit().follow()
+
+ resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
+ resp.form['date_start'] = '2021-10-01'
+ resp = resp.form.submit()
+ assert resp.context['form'].non_field_errors() == [
+ 'Agenda "Foo bar 1" has already a pricing overlapping this period.',
+ 'Agenda "Foo bar 2" has already a pricing overlapping this period.',
+ ]
+ agenda_pricing2.agendas.remove(agenda1)
+ resp = resp.form.submit()
+ assert resp.context['form'].non_field_errors() == [
+ 'Agenda "Foo bar 2" has already a pricing overlapping this period.'
+ ]
+ agenda_pricing2.agendas.remove(agenda2)
+ # ok
+ resp.form.submit().follow()
+
+
+def test_edit_agenda_pricing_overlapping_date_end(app, admin_user):
+ agenda1 = Agenda.objects.create(label='Foo bar 1')
+ agenda2 = Agenda.objects.create(label='Foo bar 2')
+ pricing = Pricing.objects.create(label='Model')
+ agenda_pricing1 = AgendaPricing.objects.create(
+ label='Foo Bar',
+ pricing=pricing,
+ date_start=datetime.date(year=2021, month=8, day=1),
+ date_end=datetime.date(year=2022, month=8, day=1),
+ )
+ agenda_pricing1.agendas.add(agenda1, agenda2)
+ agenda_pricing2 = AgendaPricing.objects.create(
+ label='Foo Bar',
+ pricing=pricing,
+ date_start=datetime.date(year=2021, month=9, day=1),
+ date_end=datetime.date(year=2022, month=9, day=1),
+ )
+ agenda_pricing2.agendas.add(agenda1, agenda2)
+
+ app = login(app)
+ resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
+ # ok, date_end has not changed
+ resp.form.submit().follow()
+
+ resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
+ # ok, no overlapping
+ resp.form['date_end'] = '2021-09-01'
+ resp.form.submit().follow()
+
+ resp = app.get('/manage/pricing/agenda-pricing/%s/edit/' % agenda_pricing1.pk)
+ resp.form['date_end'] = '2022-08-01'
+ resp = resp.form.submit()
+ assert resp.context['form'].non_field_errors() == [
+ 'Agenda "Foo bar 1" has already a pricing overlapping this period.',
+ 'Agenda "Foo bar 2" has already a pricing overlapping this period.',
+ ]
+ agenda_pricing2.agendas.remove(agenda1)
+ resp = resp.form.submit()
+ assert resp.context['form'].non_field_errors() == [
+ 'Agenda "Foo bar 2" has already a pricing overlapping this period.'
+ ]
+ agenda_pricing2.agendas.remove(agenda2)
+ # ok
+ resp.form.submit().follow()
+
+
def test_detail_agenda_pricing(app, admin_user):
pricing = Pricing.objects.create(label='Model')
agenda_pricing = AgendaPricing.objects.create(
@@ -209,9 +347,20 @@ def test_agenda_pricing_add_agenda(app, admin_user):
'This agendas has already a pricing overlapping this period.'
]
resp.form['agenda'] = agenda3.pk
- resp = resp.form.submit().follow()
+ resp.form.submit().follow()
assert list(agenda_pricing2.agendas.all()) == [agenda3]
+ agenda_pricing.flat_fee_schedule = True
+ agenda_pricing.save()
+ resp = app.get('/manage/pricing/agenda-pricing/%s/agenda/add/' % agenda_pricing2.pk)
+ assert list(resp.context['form'].fields['agenda'].queryset) == [
+ agenda1,
+ agenda2,
+ ]
+ resp.form['agenda'] = agenda1.pk
+ resp.form.submit()
+ assert list(agenda_pricing2.agendas.all()) == [agenda1, agenda3]
+
agenda_pricing.subscription_required = False
agenda_pricing.save()
app.get('/manage/pricing/agenda-pricing/%s/agenda/add/' % agenda_pricing.pk, status=404)