pricing: agenda management on agenda pricing page (#67196)
This commit is contained in:
parent
0c4ae4e39b
commit
3f9e689e1c
|
@ -23,7 +23,7 @@ from django.utils.timezone import now
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from lingo.agendas.chrono import ChronoError, get_event, get_subscriptions
|
||||
from lingo.agendas.models import CheckType
|
||||
from lingo.agendas.models import Agenda, CheckType
|
||||
from lingo.pricing.models import AgendaPricing, Criteria, CriteriaCategory, PricingError
|
||||
|
||||
|
||||
|
@ -164,6 +164,25 @@ class AgendaPricingForm(NewAgendaPricingForm):
|
|||
return slug
|
||||
|
||||
|
||||
class AgendaPricingAgendaAddForm(forms.Form):
|
||||
agenda = forms.ModelChoiceField(label=_('Agenda to add'), queryset=Agenda.objects.none(), required=True)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.agenda_pricing = kwargs.pop('agenda_pricing')
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['agenda'].queryset = Agenda.objects.exclude(agendapricings=self.agenda_pricing)
|
||||
|
||||
def clean_agenda(self):
|
||||
agenda = self.cleaned_data['agenda']
|
||||
overlapping_qs = AgendaPricing.objects.filter(agendas=agenda).extra(
|
||||
where=["(date_start, date_end) OVERLAPS (%s, %s)"],
|
||||
params=[self.agenda_pricing.date_start, self.agenda_pricing.date_end],
|
||||
)
|
||||
if overlapping_qs.exists():
|
||||
raise forms.ValidationError(_('This agendas has already a pricing overlapping this period.'))
|
||||
return agenda
|
||||
|
||||
|
||||
class PricingMatrixForm(forms.Form):
|
||||
def __init__(self, *args, **kwargs):
|
||||
matrix = kwargs.pop('matrix')
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
{% extends "lingo/pricing/manager_agenda_pricing_detail.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'lingo-manager-agenda-pricing-agenda-add' object.pk %}">{% trans "Add an agenda" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans "Add an agenda" %}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Save" %}</button>
|
||||
<a class="cancel" href="{% url 'lingo-manager-agenda-pricing-detail' object.pk %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -27,6 +27,7 @@
|
|||
<div class="pk-tabs">
|
||||
<div class="pk-tabs--tab-list" role="tablist">
|
||||
<button aria-controls="panel-options" aria-selected="true" id="tab-options" role="tab" tabindex="0">{% trans "Options" %}</button>
|
||||
<button aria-controls="panel-agendas" aria-selected="false" id="tab-agendas" role="tab" tabindex="0">{% trans "Agendas" %}</button>
|
||||
<button aria-controls="panel-debug" aria-selected="false" id="tab-debug" role="tab" tabindex="0">{% trans "Test tool" %}</button>
|
||||
{% for matrix in iter_matrix %}
|
||||
<button aria-controls="panel-matrix-{{ matrix.criteria.slug }}" aria-selected="false" id="tab-matrix-{{ matrix.criteria.slug }}" role="tab" tabindex="-1">{% trans "Pricings" context 'amount' %}{% if matrix.criteria %} - {{ matrix.criteria.label }}{% endif %}</button>
|
||||
|
@ -43,6 +44,22 @@
|
|||
</ul>
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-agendas" hidden id="panel-agendas" role="tabpanel" tabindex="0">
|
||||
<ul class="objects-list single-links">
|
||||
{% for agenda in object.agendas.all %}
|
||||
<li>
|
||||
<a href="{% url 'lingo-manager-agenda-detail' pk=agenda.pk %}">
|
||||
{{ agenda.label }}
|
||||
</a>
|
||||
<a class="delete" rel="popup" href="{% url 'lingo-manager-agenda-pricing-agenda-delete' object.pk agenda.pk %}">{% trans "remove"%}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div class="panel--buttons">
|
||||
<a class="pk-button" rel="popup" href="{% url 'lingo-manager-agenda-pricing-agenda-add' object.pk %}">{% trans "Add an agenda" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-debug" hidden id="panel-debug" role="tabpanel" tabindex="0">
|
||||
<form method="get" enctype="multipart/form-data" action="{% url 'lingo-manager-agenda-pricing-test-tool' object.pk %}">
|
||||
{{ test_tool_form.as_p }}
|
||||
|
|
|
@ -188,6 +188,16 @@ urlpatterns = [
|
|||
views.agenda_pricing_test_tool,
|
||||
name='lingo-manager-agenda-pricing-test-tool',
|
||||
),
|
||||
url(
|
||||
r'^agenda-pricing/(?P<pk>\d+)/agenda/add/$',
|
||||
views.agenda_pricing_agenda_add,
|
||||
name='lingo-manager-agenda-pricing-agenda-add',
|
||||
),
|
||||
url(
|
||||
r'^agenda-pricing/(?P<pk>\d+)/agenda/(?P<agenda_pk>\d+)/delete/$',
|
||||
views.agenda_pricing_agenda_delete,
|
||||
name='lingo-manager-agenda-pricing-agenda-delete',
|
||||
),
|
||||
url(
|
||||
r'^agenda-pricing/(?P<pk>\d+)/matrix/edit/$',
|
||||
views.agenda_pricing_matrix_edit,
|
||||
|
|
|
@ -44,6 +44,7 @@ from lingo.agendas.chrono import refresh_agendas
|
|||
from lingo.agendas.models import Agenda, CheckType, CheckTypeGroup
|
||||
from lingo.agendas.views import AgendaMixin
|
||||
from lingo.pricing.forms import (
|
||||
AgendaPricingAgendaAddForm,
|
||||
AgendaPricingForm,
|
||||
CheckTypeForm,
|
||||
CriteriaForm,
|
||||
|
@ -827,6 +828,61 @@ class AgendaPricingExport(DetailView):
|
|||
agenda_pricing_export = AgendaPricingExport.as_view()
|
||||
|
||||
|
||||
class AgendaPricingAgendaAddView(FormView):
|
||||
template_name = 'lingo/pricing/manager_agenda_pricing_agenda_form.html'
|
||||
model = AgendaPricing
|
||||
form_class = AgendaPricingAgendaAddForm
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.object = get_object_or_404(AgendaPricing, pk=kwargs['pk'])
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['agenda_pricing'] = self.object
|
||||
return kwargs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['object'] = self.object
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
self.object.agendas.add(form.cleaned_data['agenda'])
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return '%s#open:agendas' % reverse('lingo-manager-agenda-pricing-detail', args=[self.object.pk])
|
||||
|
||||
|
||||
agenda_pricing_agenda_add = AgendaPricingAgendaAddView.as_view()
|
||||
|
||||
|
||||
class AgendaPricingAgendaDeleteView(DeleteView):
|
||||
template_name = 'lingo/manager_confirm_delete.html'
|
||||
model = Agenda
|
||||
pk_url_kwarg = 'agenda_pk'
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.agenda_pricing = get_object_or_404(AgendaPricing, pk=kwargs['pk'])
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self):
|
||||
return self.agenda_pricing.agendas.all()
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
self.agenda_pricing.agendas.remove(self.object)
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
def get_success_url(self):
|
||||
return '%s#open:agendas' % reverse(
|
||||
'lingo-manager-agenda-pricing-detail', args=[self.agenda_pricing.pk]
|
||||
)
|
||||
|
||||
|
||||
agenda_pricing_agenda_delete = AgendaPricingAgendaDeleteView.as_view()
|
||||
|
||||
|
||||
class AgendaPricingMatrixEdit(FormView):
|
||||
template_name = 'lingo/pricing/manager_agenda_pricing_matrix_form.html'
|
||||
|
||||
|
|
|
@ -117,6 +117,91 @@ def test_delete_agenda_pricing(app, admin_user):
|
|||
assert AgendaPricing.objects.exists() is False
|
||||
|
||||
|
||||
def test_agenda_pricing_add_agenda(app, admin_user):
|
||||
pricing = Pricing.objects.create(label='Model')
|
||||
agenda_pricing = AgendaPricing.objects.create(
|
||||
pricing=pricing,
|
||||
date_start=datetime.date(year=2021, month=9, day=1),
|
||||
date_end=datetime.date(year=2022, month=9, day=1),
|
||||
)
|
||||
agenda1 = Agenda.objects.create(label='Foo bar 1')
|
||||
agenda2 = Agenda.objects.create(label='Foo bar 2')
|
||||
agenda3 = Agenda.objects.create(label='Foo bar 3')
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/pricing/agenda-pricing/%s/' % agenda_pricing.pk)
|
||||
resp = resp.click(href='/manage/pricing/agenda-pricing/%s/agenda/add/' % agenda_pricing.pk)
|
||||
assert list(resp.context['form'].fields['agenda'].queryset) == [
|
||||
agenda1,
|
||||
agenda2,
|
||||
agenda3,
|
||||
]
|
||||
resp.form['agenda'] = agenda1.pk
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/manage/pricing/agenda-pricing/%s/#open:agendas' % agenda_pricing.pk)
|
||||
resp = resp.follow()
|
||||
assert list(agenda_pricing.agendas.all()) == [agenda1]
|
||||
|
||||
resp = app.get('/manage/pricing/agenda-pricing/%s/agenda/add/' % agenda_pricing.pk)
|
||||
assert list(resp.context['form'].fields['agenda'].queryset) == [
|
||||
agenda2,
|
||||
agenda3,
|
||||
]
|
||||
resp.form['agenda'] = agenda2.pk
|
||||
resp = resp.form.submit().follow()
|
||||
assert list(agenda_pricing.agendas.all()) == [agenda1, agenda2]
|
||||
|
||||
agenda_pricing2 = AgendaPricing.objects.create(
|
||||
pricing=pricing,
|
||||
date_start=datetime.date(year=2021, month=11, day=1),
|
||||
date_end=datetime.date(year=2022, month=11, day=1),
|
||||
)
|
||||
resp = app.get('/manage/pricing/agenda-pricing/%s/agenda/add/' % agenda_pricing2.pk)
|
||||
assert list(resp.context['form'].fields['agenda'].queryset) == [
|
||||
agenda1,
|
||||
agenda2,
|
||||
agenda3,
|
||||
]
|
||||
resp.form['agenda'] = agenda1.pk
|
||||
resp = resp.form.submit()
|
||||
assert resp.context['form'].errors['agenda'] == [
|
||||
'This agendas has already a pricing overlapping this period.'
|
||||
]
|
||||
resp.form['agenda'] = agenda3.pk
|
||||
resp = resp.form.submit().follow()
|
||||
assert list(agenda_pricing2.agendas.all()) == [agenda3]
|
||||
|
||||
|
||||
def test_agenda_pricing_delete_agenda(app, admin_user):
|
||||
pricing = Pricing.objects.create(label='Model')
|
||||
agenda_pricing = AgendaPricing.objects.create(
|
||||
pricing=pricing,
|
||||
date_start=datetime.date(year=2021, month=9, day=1),
|
||||
date_end=datetime.date(year=2022, month=9, day=1),
|
||||
)
|
||||
agenda1 = Agenda.objects.create(label='Foo bar 1')
|
||||
agenda2 = Agenda.objects.create(label='Foo bar 2')
|
||||
Agenda.objects.create(label='Foo bar 3')
|
||||
agenda_pricing.agendas.add(agenda1, agenda2)
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/pricing/agenda-pricing/%s/' % agenda_pricing.pk)
|
||||
resp = resp.click(
|
||||
href='/manage/pricing/agenda-pricing/%s/agenda/%s/delete/' % (agenda_pricing.pk, agenda1.pk)
|
||||
)
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/manage/pricing/agenda-pricing/%s/#open:agendas' % agenda_pricing.pk)
|
||||
resp = resp.follow()
|
||||
assert list(agenda_pricing.agendas.all()) == [agenda2]
|
||||
|
||||
# not linked
|
||||
app.get(
|
||||
'/manage/pricing/agenda-pricing/%s/agenda/%s/delete/' % (agenda_pricing.pk, agenda1.pk), status=404
|
||||
)
|
||||
# unknown
|
||||
app.get('/manage/pricing/agenda-pricing/%s/agenda/%s/delete/' % (agenda_pricing.pk, 0), status=404)
|
||||
|
||||
|
||||
def test_detail_agenda_pricing_3_categories(app, admin_user):
|
||||
category1 = CriteriaCategory.objects.create(label='Cat 1')
|
||||
Criteria.objects.create(label='Crit 1-1', slug='crit-1-1', category=category1, order=1)
|
||||
|
|
Loading…
Reference in New Issue