pricing: flat fee schedule & overlapping (#67675)

This commit is contained in:
Lauréline Guérin 2022-07-26 10:45:05 +02:00
parent e313095863
commit a1eff5cb91
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
4 changed files with 212 additions and 3 deletions

View File

@ -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],
)

View File

@ -26,6 +26,7 @@
<div class="pk-tabs--container">
<div aria-labelledby="tab-pricings" id="panel-pricings" role="tabpanel" tabindex="0">
<h3>{% trans "Pricings" context 'agenda pricing' %}</h3>
{% if agenda_pricings %}
<ul class="objects-list single-links">
{% for agenda_pricing in agenda_pricings %}
@ -42,6 +43,23 @@
{% endblocktrans %}
</div>
{% endif %}
<h3>{% trans "Flat fee schedule pricings" %}</h3>
{% if agenda_pricings_flat %}
<ul class="objects-list single-links">
{% for agenda_pricing in agenda_pricings_flat %}
<li>
<a href="{% url 'lingo-manager-agenda-pricing-detail' agenda_pricing.pk %}">{{ agenda_pricing.pricing }} ({{ agenda_pricing.date_start|date:'d/m/Y' }} - {{ agenda_pricing.date_end|date:'d/m/Y' }})</a>
<a href="{% url 'lingo-manager-pricing-detail' agenda_pricing.pricing.pk %}" class="link-action-icon link">{% trans "see" %}</a>
</li>
{% endfor %}
</ul>
{% else %}
<div class="big-msg-info">
{% blocktrans %}
This agenda doesn't have any flat fee schedule pricing defined yet.
{% endblocktrans %}
</div>
{% endif %}
</div>
<div aria-labelledby="tab-check" hidden="" id="panel-check" role="tabpanel" tabindex="0">

View File

@ -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')
)

View File

@ -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)