pricing: configuration of pricing models (#64903)
This commit is contained in:
parent
81722913a4
commit
306ec0e5ce
|
@ -523,6 +523,20 @@ table.timesheet {
|
|||
height: 20px;
|
||||
}
|
||||
|
||||
div.paragraph {
|
||||
background: white;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #386ede;
|
||||
border-radius: 3px;
|
||||
max-width: 100%;
|
||||
padding: 5px 15px;
|
||||
margin-bottom: 1rem;
|
||||
h4 {
|
||||
margin-top: 5px;
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
ul.objects-list.sortable {
|
||||
li {
|
||||
position: relative;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<li><a href="{% url 'chrono-manager-events-type-list' %}">{% trans 'Events types' %}</a></li>
|
||||
<li><a href="{% url 'chrono-manager-check-type-list' %}">{% trans 'Check types' %}</a></li>
|
||||
{% if pricing_enabled %}
|
||||
<li><a href="{% url 'chrono-manager-pricing-criteria-list' %}">{% trans 'Pricing' context 'pricing' %}</a></li>
|
||||
<li><a href="{% url 'chrono-manager-pricing-list' %}">{% trans 'Pricing' context 'pricing' %}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if has_access_to_unavailability_calendars %}
|
||||
|
|
|
@ -19,7 +19,7 @@ from django.forms import ValidationError
|
|||
from django.template import Template, TemplateSyntaxError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from chrono.pricing.models import Criteria
|
||||
from chrono.pricing.models import Criteria, CriteriaCategory
|
||||
|
||||
|
||||
class NewCriteriaForm(forms.ModelForm):
|
||||
|
@ -49,3 +49,30 @@ class CriteriaForm(NewCriteriaForm):
|
|||
raise ValidationError(_('Another criteria exists with the same identifier.'))
|
||||
|
||||
return slug
|
||||
|
||||
|
||||
class PricingCriteriaCategoryAddForm(forms.Form):
|
||||
category = forms.ModelChoiceField(
|
||||
label=_('Criteria category to add'), queryset=CriteriaCategory.objects.none(), required=True
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.pricing = kwargs.pop('pricing')
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['category'].queryset = CriteriaCategory.objects.exclude(pricings=self.pricing)
|
||||
|
||||
|
||||
class PricingCriteriaCategoryEditForm(forms.Form):
|
||||
criterias = forms.ModelMultipleChoiceField(
|
||||
label=_('Criterias'),
|
||||
queryset=Criteria.objects.none(),
|
||||
required=True,
|
||||
widget=forms.CheckboxSelectMultiple(),
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.pricing = kwargs.pop('pricing')
|
||||
self.category = kwargs.pop('category')
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['criterias'].queryset = self.category.criterias.all()
|
||||
self.initial['criterias'] = self.pricing.criterias.filter(category=self.category)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% extends "chrono/manager_base.html" %}
|
||||
{% extends "chrono/pricing/manager_pricing_list.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
|
@ -16,7 +16,7 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="pk-information">
|
||||
<p>{% trans "Define here pricing criterias used in events agendas." %}</p>
|
||||
<p>{% trans "Define here pricing criterias used in pricing models." %}</p>
|
||||
</div>
|
||||
{% if object_list %}
|
||||
<p class="hint">
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
{% extends "chrono/pricing/manager_pricing_list.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'chrono-manager-pricing-detail' object.pk %}">{{ object }}</a>
|
||||
{% if category %}
|
||||
<a href="{% url 'chrono-manager-pricing-criteria-category-edit' object.pk category.pk %}">{% trans "Select criterias" %}</a>
|
||||
{% else %}
|
||||
<a href="{% url 'chrono-manager-pricing-criteria-category-add' object.pk %}">{% trans "Add a category" %}</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
{% if category %}
|
||||
<h2>{% trans "Select criterias" %}</h2>
|
||||
{% else %}
|
||||
<h2>{% trans "Add a category" %}</h2>
|
||||
{% endif %}
|
||||
{% 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 'chrono-manager-pricing-detail' object.pk %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -0,0 +1,53 @@
|
|||
{% extends "chrono/pricing/manager_pricing_list.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'chrono-manager-pricing-detail' object.pk %}">{{ object }}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>
|
||||
{{ object }}
|
||||
<span class="identifier">[{% trans "identifier:" %} {{ object.slug }}]</span>
|
||||
</h2>
|
||||
<span class="actions">
|
||||
<a class="extra-actions-menu-opener"></a>
|
||||
<ul class="extra-actions-menu">
|
||||
<li><a rel="popup" href="{% url 'chrono-manager-pricing-edit' pk=object.pk %}">{% trans 'Options' %}</a></li>
|
||||
<li><a rel="popup" href="{% url 'chrono-manager-pricing-delete' pk=object.pk %}">{% trans 'Delete' %}</a></li>
|
||||
</ul>
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="section">
|
||||
<h3>{% trans "Criterias" %}</h3>
|
||||
<div>
|
||||
{% with criterias=object.criterias.all %}
|
||||
{% for category in object.categories.all %}
|
||||
<div class="paragraph">
|
||||
<h4>{% trans "Category:" %} {{ category }}</h4>
|
||||
<p>{% trans "Selected criterias:" %}</p>
|
||||
<ul>
|
||||
{% for criteria in criterias %}
|
||||
{% if criteria.category == category %}
|
||||
<li>{{ criteria }}</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<p>
|
||||
<a rel="popup" class="pk-button" href="{% url 'chrono-manager-pricing-criteria-category-edit' pk=object.pk category_pk=category.pk %}">{% trans "Change criterias selection" %}</a>
|
||||
<a rel="popup" class="pk-button" href="{% url 'chrono-manager-pricing-criteria-category-delete' pk=object.pk category_pk=category.pk %}">{% trans "Remove this category" %}</a>
|
||||
</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endwith %}
|
||||
{% if object.categories.count < 3 %}
|
||||
<p>
|
||||
<a rel="popup" class="pk-button" href="{% url 'chrono-manager-pricing-criteria-category-add' pk=object.pk %}">{% trans "Add a category" %} <span class="extra-info">({% trans "max 3 categories" %})</span></a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,31 @@
|
|||
{% extends "chrono/pricing/manager_pricing_list.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
{% if object.pk %}
|
||||
<a href="{% url 'chrono-manager-pricing-detail' object.pk %}">{{ object }}</a>
|
||||
<a href="{% url 'chrono-manager-pricing-edit' object.pk %}">{% trans "Edit" %}</a>
|
||||
{% else %}
|
||||
<a href="{% url 'chrono-manager-pricing-add' %}">{% trans "New pricing model" %}</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
{% if object.pk %}
|
||||
<h2>{% trans "Edit pricing model" %}</h2>
|
||||
{% else %}
|
||||
<h2>{% trans "New pricing model" %}</h2>
|
||||
{% endif %}
|
||||
{% 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 'chrono-manager-pricing-list' %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -0,0 +1,39 @@
|
|||
{% extends "chrono/manager_base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'chrono-manager-pricing-list' %}">{% trans "Pricing" context 'pricing' %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans 'Pricing' context 'pricing' %}</h2>
|
||||
<span class="actions">
|
||||
<a href="{% url 'chrono-manager-pricing-criteria-list' %}">{% trans 'Criterias' %}</a>
|
||||
<a rel="popup" href="{% url 'chrono-manager-pricing-add' %}">{% trans 'New pricing model' %}</a>
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="pk-information">
|
||||
<p>{% trans "Define here pricing models used in events agendas." %}</p>
|
||||
</div>
|
||||
{% if object_list %}
|
||||
<div>
|
||||
<ul class="objects-list single-links">
|
||||
{% for object in object_list %}
|
||||
<li>
|
||||
<a href="{% url 'chrono-manager-pricing-detail' pk=object.pk %}">{{ object.label }} ({{ object.slug }})</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="big-msg-info">
|
||||
{% blocktrans %}
|
||||
This site doesn't have any pricing model yet. Click on the "New" button in the top
|
||||
right of the page to add a first one.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -19,6 +19,42 @@ from django.conf.urls import url
|
|||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.pricing_list, name='chrono-manager-pricing-list'),
|
||||
url(
|
||||
r'^add/$',
|
||||
views.pricing_add,
|
||||
name='chrono-manager-pricing-add',
|
||||
),
|
||||
url(
|
||||
r'^(?P<pk>\d+)/$',
|
||||
views.pricing_detail,
|
||||
name='chrono-manager-pricing-detail',
|
||||
),
|
||||
url(
|
||||
r'^(?P<pk>\d+)/edit/$',
|
||||
views.pricing_edit,
|
||||
name='chrono-manager-pricing-edit',
|
||||
),
|
||||
url(
|
||||
r'^(?P<pk>\d+)/delete/$',
|
||||
views.pricing_delete,
|
||||
name='chrono-manager-pricing-delete',
|
||||
),
|
||||
url(
|
||||
r'^(?P<pk>\d+)/category/add/$',
|
||||
views.pricing_criteria_category_add,
|
||||
name='chrono-manager-pricing-criteria-category-add',
|
||||
),
|
||||
url(
|
||||
r'^(?P<pk>\d+)/category/(?P<category_pk>\d+)/edit/$',
|
||||
views.pricing_criteria_category_edit,
|
||||
name='chrono-manager-pricing-criteria-category-edit',
|
||||
),
|
||||
url(
|
||||
r'^(?P<pk>\d+)/category/(?P<category_pk>\d+)/delete/$',
|
||||
views.pricing_criteria_category_delete,
|
||||
name='chrono-manager-pricing-criteria-category-delete',
|
||||
),
|
||||
url(r'^criterias/$', views.criteria_list, name='chrono-manager-pricing-criteria-list'),
|
||||
url(
|
||||
r'^criteria/category/add/$',
|
||||
|
|
|
@ -18,12 +18,32 @@ import datetime
|
|||
import json
|
||||
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import HttpResponse, HttpResponseBadRequest
|
||||
from django.db.models import Prefetch
|
||||
from django.http import Http404, HttpResponse, HttpResponseBadRequest, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse
|
||||
from django.views.generic import CreateView, DeleteView, DetailView, ListView, UpdateView
|
||||
from django.views.generic import CreateView, DeleteView, DetailView, FormView, ListView, UpdateView
|
||||
|
||||
from chrono.pricing.forms import CriteriaForm, NewCriteriaForm
|
||||
from chrono.pricing.models import Criteria, CriteriaCategory
|
||||
from chrono.pricing.forms import (
|
||||
CriteriaForm,
|
||||
NewCriteriaForm,
|
||||
PricingCriteriaCategoryAddForm,
|
||||
PricingCriteriaCategoryEditForm,
|
||||
)
|
||||
from chrono.pricing.models import Criteria, CriteriaCategory, Pricing, PricingCriteriaCategory
|
||||
|
||||
|
||||
class PricingListView(ListView):
|
||||
template_name = 'chrono/pricing/manager_pricing_list.html'
|
||||
model = Pricing
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_staff:
|
||||
raise PermissionDenied()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
pricing_list = PricingListView.as_view()
|
||||
|
||||
|
||||
class CriteriaListView(ListView):
|
||||
|
@ -42,6 +62,178 @@ class CriteriaListView(ListView):
|
|||
criteria_list = CriteriaListView.as_view()
|
||||
|
||||
|
||||
class PricingAddView(CreateView):
|
||||
template_name = 'chrono/pricing/manager_pricing_form.html'
|
||||
model = Pricing
|
||||
fields = ['label']
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_staff:
|
||||
raise PermissionDenied()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-pricing-detail', args=[self.object.pk])
|
||||
|
||||
|
||||
pricing_add = PricingAddView.as_view()
|
||||
|
||||
|
||||
class PricingDetailView(DetailView):
|
||||
template_name = 'chrono/pricing/manager_pricing_detail.html'
|
||||
model = Pricing
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_staff:
|
||||
raise PermissionDenied()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self):
|
||||
return (
|
||||
super()
|
||||
.get_queryset()
|
||||
.prefetch_related(
|
||||
Prefetch(
|
||||
'categories', queryset=CriteriaCategory.objects.order_by('pricingcriteriacategory__order')
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
pricing_detail = PricingDetailView.as_view()
|
||||
|
||||
|
||||
class PricingEditView(UpdateView):
|
||||
template_name = 'chrono/pricing/manager_pricing_form.html'
|
||||
model = Pricing
|
||||
fields = ['label', 'slug']
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_staff:
|
||||
raise PermissionDenied()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-pricing-detail', args=[self.object.pk])
|
||||
|
||||
|
||||
pricing_edit = PricingEditView.as_view()
|
||||
|
||||
|
||||
class PricingDeleteView(DeleteView):
|
||||
template_name = 'chrono/manager_confirm_delete.html'
|
||||
model = Pricing
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
if not request.user.is_staff:
|
||||
raise PermissionDenied()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-pricing-list')
|
||||
|
||||
|
||||
pricing_delete = PricingDeleteView.as_view()
|
||||
|
||||
|
||||
class PricingCriteriaCategoryAddView(FormView):
|
||||
template_name = 'chrono/pricing/manager_pricing_criteria_category_form.html'
|
||||
model = Pricing
|
||||
form_class = PricingCriteriaCategoryAddForm
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.object = get_object_or_404(Pricing, pk=kwargs['pk'])
|
||||
if self.object.categories.count() >= 3:
|
||||
raise Http404
|
||||
if not request.user.is_staff:
|
||||
raise PermissionDenied()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['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):
|
||||
PricingCriteriaCategory.objects.create(pricing=self.object, category=form.cleaned_data['category'])
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-pricing-detail', args=[self.object.pk])
|
||||
|
||||
|
||||
pricing_criteria_category_add = PricingCriteriaCategoryAddView.as_view()
|
||||
|
||||
|
||||
class PricingCriteriaCategoryEditView(FormView):
|
||||
template_name = 'chrono/pricing/manager_pricing_criteria_category_form.html'
|
||||
model = Pricing
|
||||
form_class = PricingCriteriaCategoryEditForm
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.object = get_object_or_404(Pricing, pk=kwargs['pk'])
|
||||
self.category = get_object_or_404(self.object.categories, pk=kwargs['category_pk'])
|
||||
if not request.user.is_staff:
|
||||
raise PermissionDenied()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['pricing'] = self.object
|
||||
kwargs['category'] = self.category
|
||||
return kwargs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['object'] = self.object
|
||||
kwargs['category'] = self.category
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
def form_valid(self, form):
|
||||
old_criterias = self.object.criterias.filter(category=self.category)
|
||||
new_criterias = form.cleaned_data['criterias']
|
||||
removed_criterias = set(old_criterias) - set(new_criterias)
|
||||
self.object.criterias.remove(*removed_criterias)
|
||||
self.object.criterias.add(*new_criterias)
|
||||
return super().form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-pricing-detail', args=[self.object.pk])
|
||||
|
||||
|
||||
pricing_criteria_category_edit = PricingCriteriaCategoryEditView.as_view()
|
||||
|
||||
|
||||
class PricingCriteriaCategoryDeleteView(DeleteView):
|
||||
template_name = 'chrono/manager_confirm_delete.html'
|
||||
model = CriteriaCategory
|
||||
pk_url_kwarg = 'category_pk'
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.pricing = get_object_or_404(Pricing, pk=kwargs['pk'])
|
||||
if not request.user.is_staff:
|
||||
raise PermissionDenied()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_queryset(self):
|
||||
return self.pricing.categories.all()
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
self.pricing.categories.remove(self.object)
|
||||
self.pricing.criterias.remove(*self.pricing.criterias.filter(category=self.object))
|
||||
return HttpResponseRedirect(self.get_success_url())
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('chrono-manager-pricing-detail', args=[self.pricing.pk])
|
||||
|
||||
|
||||
pricing_criteria_category_delete = PricingCriteriaCategoryDeleteView.as_view()
|
||||
|
||||
|
||||
class CriteriaCategoryAddView(CreateView):
|
||||
template_name = 'chrono/pricing/manager_criteria_category_form.html'
|
||||
model = CriteriaCategory
|
||||
|
|
|
@ -5,7 +5,7 @@ import pytest
|
|||
from webtest import Upload
|
||||
|
||||
from chrono.agendas.models import Agenda
|
||||
from chrono.pricing.models import Criteria, CriteriaCategory
|
||||
from chrono.pricing.models import Criteria, CriteriaCategory, Pricing, PricingCriteriaCategory
|
||||
from tests.utils import login
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
@ -19,18 +19,256 @@ def agenda_with_restrictions(manager_user):
|
|||
return agenda
|
||||
|
||||
|
||||
def test_list_criterias_as_manager(app, manager_user, agenda_with_restrictions):
|
||||
def test_list_pricings_as_manager(app, manager_user, agenda_with_restrictions):
|
||||
app = login(app, username='manager', password='manager')
|
||||
app.get('/manage/pricing/criterias/', status=403)
|
||||
app.get('/manage/pricing/', status=403)
|
||||
|
||||
resp = app.get('/manage/')
|
||||
assert 'Pricing' not in resp.text
|
||||
|
||||
|
||||
def test_add_pricing(settings, app, admin_user):
|
||||
app = login(app)
|
||||
resp = app.get('/manage/')
|
||||
resp = resp.click('Pricing')
|
||||
resp = resp.click('New pricing model')
|
||||
resp.form['label'] = 'Pricing model for lunch'
|
||||
resp = resp.form.submit()
|
||||
pricing = Pricing.objects.latest('pk')
|
||||
assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
|
||||
assert pricing.label == 'Pricing model for lunch'
|
||||
assert pricing.slug == 'pricing-model-for-lunch'
|
||||
|
||||
settings.CHRONO_ENABLE_PRICING = False
|
||||
resp = app.get('/manage/')
|
||||
assert 'Pricing' not in resp.text
|
||||
|
||||
|
||||
def test_add_pricing_as_manager(app, manager_user):
|
||||
app = login(app, username='manager', password='manager')
|
||||
app.get('/manage/pricing/add/', status=403)
|
||||
|
||||
|
||||
def test_detail_pricing(app, admin_user):
|
||||
pricing = Pricing.objects.create(label='Model')
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/pricing/')
|
||||
resp = resp.click(href='/manage/pricing/%s/' % pricing.pk)
|
||||
assert '/manage/pricing/%s/edit/' % pricing.pk in resp
|
||||
assert '/manage/pricing/%s/delete/' % pricing.pk in resp
|
||||
|
||||
|
||||
def test_detail_pricing_as_manager(app, manager_user):
|
||||
pricing = Pricing.objects.create(label='Model')
|
||||
|
||||
app = login(app, username='manager', password='manager')
|
||||
app.get('/manage/pricing/%s/' % pricing.pk, status=403)
|
||||
|
||||
|
||||
def test_edit_pricing(app, admin_user):
|
||||
pricing = Pricing.objects.create(label='Model 1')
|
||||
pricing2 = Pricing.objects.create(label='Model 2')
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/pricing/%s/' % pricing.pk)
|
||||
resp = resp.click(href='/manage/pricing/%s/edit/' % pricing.pk)
|
||||
resp.form['label'] = 'Model Foo'
|
||||
resp.form['slug'] = pricing2.slug
|
||||
resp = resp.form.submit()
|
||||
assert resp.context['form'].errors['slug'] == ['Pricing with this Identifier already exists.']
|
||||
|
||||
resp.form['slug'] = 'foo-bar'
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
|
||||
pricing.refresh_from_db()
|
||||
assert pricing.label == 'Model Foo'
|
||||
assert pricing.slug == 'foo-bar'
|
||||
|
||||
|
||||
def test_edit_pricing_as_manager(app, manager_user):
|
||||
pricing = Pricing.objects.create(label='Model')
|
||||
|
||||
app = login(app, username='manager', password='manager')
|
||||
app.get('/manage/pricing/%s/edit/' % pricing.pk, status=403)
|
||||
|
||||
|
||||
def test_delete_pricing(app, admin_user):
|
||||
pricing = Pricing.objects.create(label='Model')
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/pricing/%s/' % pricing.pk)
|
||||
resp = resp.click(href='/manage/pricing/%s/delete/' % pricing.pk)
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/manage/pricing/')
|
||||
assert Pricing.objects.exists() is False
|
||||
|
||||
|
||||
def test_delete_pricing_as_manager(app, manager_user):
|
||||
pricing = Pricing.objects.create(label='Model')
|
||||
|
||||
app = login(app, username='manager', password='manager')
|
||||
app.get('/manage/pricing/%s/delete/' % pricing.pk, status=403)
|
||||
|
||||
|
||||
def test_pricing_add_category(app, admin_user):
|
||||
pricing = Pricing.objects.create(label='Model')
|
||||
category1 = CriteriaCategory.objects.create(label='Cat 1')
|
||||
category2 = CriteriaCategory.objects.create(label='Cat 2')
|
||||
category3 = CriteriaCategory.objects.create(label='Cat 3')
|
||||
category4 = CriteriaCategory.objects.create(label='Cat 4')
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/pricing/%s/' % pricing.pk)
|
||||
resp = resp.click(href='/manage/pricing/%s/category/add/' % pricing.pk)
|
||||
assert list(resp.context['form'].fields['category'].queryset) == [
|
||||
category1,
|
||||
category2,
|
||||
category3,
|
||||
category4,
|
||||
]
|
||||
resp.form['category'] = category1.pk
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
|
||||
resp = resp.follow()
|
||||
assert '/manage/pricing/%s/category/add/' % pricing.pk in resp
|
||||
assert list(
|
||||
PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
|
||||
) == [category1.pk]
|
||||
assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
|
||||
1
|
||||
]
|
||||
|
||||
resp = app.get('/manage/pricing/%s/category/add/' % pricing.pk)
|
||||
assert list(resp.context['form'].fields['category'].queryset) == [category2, category3, category4]
|
||||
resp.form['category'] = category4.pk
|
||||
resp = resp.form.submit().follow()
|
||||
assert list(
|
||||
PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
|
||||
) == [category1.pk, category4.pk]
|
||||
assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
|
||||
1,
|
||||
2,
|
||||
]
|
||||
|
||||
resp = app.get('/manage/pricing/%s/category/add/' % pricing.pk)
|
||||
assert list(resp.context['form'].fields['category'].queryset) == [category2, category3]
|
||||
resp.form['category'] = category2.pk
|
||||
resp = resp.form.submit().follow()
|
||||
assert '/manage/pricing/%s/category/add/' % pricing.pk not in resp
|
||||
assert list(
|
||||
PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
|
||||
) == [category1.pk, category4.pk, category2.pk]
|
||||
assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
]
|
||||
|
||||
app.get('/manage/pricing/%s/category/add/' % pricing.pk, status=404)
|
||||
|
||||
|
||||
def test_pricing_add_category_as_manager(app, manager_user):
|
||||
pricing = Pricing.objects.create(label='Model')
|
||||
|
||||
app = login(app, username='manager', password='manager')
|
||||
app.get('/manage/pricing/%s/category/add/' % pricing.pk, status=403)
|
||||
|
||||
|
||||
def test_pricing_edit_category(app, admin_user):
|
||||
category1 = CriteriaCategory.objects.create(label='Cat 1')
|
||||
criteria1 = Criteria.objects.create(label='Crit 1', category=category1)
|
||||
criteria2 = Criteria.objects.create(label='Crit 2', category=category1)
|
||||
criteria3 = Criteria.objects.create(label='Crit 3', category=category1)
|
||||
criteria4 = Criteria.objects.create(label='Crit 4', category=category1)
|
||||
category2 = CriteriaCategory.objects.create(label='cat 2')
|
||||
criteria5 = Criteria.objects.create(label='Crit 5', category=category2)
|
||||
pricing = Pricing.objects.create(label='Model')
|
||||
pricing.categories.add(category1, through_defaults={'order': 1})
|
||||
pricing.categories.add(category2, through_defaults={'order': 2})
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/pricing/%s/' % pricing.pk)
|
||||
resp = resp.click(href='/manage/pricing/%s/category/%s/edit/' % (pricing.pk, category1.pk))
|
||||
assert list(resp.context['form'].fields['criterias'].queryset) == [
|
||||
criteria1,
|
||||
criteria2,
|
||||
criteria3,
|
||||
criteria4,
|
||||
]
|
||||
assert list(resp.context['form'].initial['criterias']) == []
|
||||
resp.form['criterias'] = [criteria1.pk, criteria3.pk]
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
|
||||
resp = resp.follow()
|
||||
assert list(pricing.criterias.order_by('pk')) == [criteria1, criteria3]
|
||||
|
||||
resp = app.get('/manage/pricing/%s/category/%s/edit/' % (pricing.pk, category1.pk))
|
||||
assert list(resp.context['form'].initial['criterias']) == [criteria1, criteria3]
|
||||
resp.form['criterias'] = [criteria1.pk, criteria4.pk]
|
||||
resp = resp.form.submit().follow()
|
||||
assert list(pricing.criterias.order_by('pk')) == [criteria1, criteria4]
|
||||
|
||||
resp = app.get('/manage/pricing/%s/category/%s/edit/' % (pricing.pk, category2.pk))
|
||||
assert list(resp.context['form'].fields['criterias'].queryset) == [criteria5]
|
||||
assert list(resp.context['form'].initial['criterias']) == []
|
||||
resp.form['criterias'] = [criteria5.pk]
|
||||
resp = resp.form.submit().follow()
|
||||
assert list(pricing.criterias.order_by('pk')) == [criteria1, criteria4, criteria5]
|
||||
|
||||
|
||||
def test_pricing_edit_category_as_manager(app, manager_user):
|
||||
pricing = Pricing.objects.create(label='Model')
|
||||
category = CriteriaCategory.objects.create(label='Cat')
|
||||
pricing.categories.add(category, through_defaults={'order': 1})
|
||||
|
||||
app = login(app, username='manager', password='manager')
|
||||
app.get('/manage/pricing/%s/category/%s/edit/' % (pricing.pk, category.pk), status=403)
|
||||
|
||||
|
||||
def test_pricing_delete_category(app, admin_user):
|
||||
category1 = CriteriaCategory.objects.create(label='Cat 1')
|
||||
criteria1 = Criteria.objects.create(label='Crit 1', category=category1)
|
||||
category2 = CriteriaCategory.objects.create(label='Cat 2')
|
||||
criteria2 = Criteria.objects.create(label='Crit 2', category=category2)
|
||||
pricing = Pricing.objects.create(label='Model')
|
||||
pricing.categories.add(category1, through_defaults={'order': 1})
|
||||
pricing.categories.add(category2, through_defaults={'order': 2})
|
||||
pricing.criterias.add(criteria1, criteria2)
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/pricing/%s/' % pricing.pk)
|
||||
resp = resp.click(href='/manage/pricing/%s/category/%s/delete/' % (pricing.pk, category1.pk))
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
|
||||
resp = resp.follow()
|
||||
assert list(pricing.categories.all()) == [category2]
|
||||
assert list(pricing.criterias.all()) == [criteria2]
|
||||
|
||||
# not linked
|
||||
app.get('/manage/pricing/%s/category/%s/delete/' % (pricing.pk, category1.pk), status=404)
|
||||
# unknown
|
||||
app.get('/manage/pricing/%s/category/%s/delete/' % (pricing.pk, 0), status=404)
|
||||
|
||||
|
||||
def test_pricing_delete_category_as_manager(app, manager_user):
|
||||
pricing = Pricing.objects.create(label='Model')
|
||||
category = CriteriaCategory.objects.create(label='Cat')
|
||||
|
||||
app = login(app, username='manager', password='manager')
|
||||
app.get('/manage/pricing/%s/category/%s/delete/' % (pricing.pk, category.pk), status=403)
|
||||
|
||||
|
||||
def test_list_criterias_as_manager(app, manager_user):
|
||||
app = login(app, username='manager', password='manager')
|
||||
app.get('/manage/pricing/criterias/', status=403)
|
||||
|
||||
|
||||
def test_add_category(settings, app, admin_user):
|
||||
app = login(app)
|
||||
resp = app.get('/manage/')
|
||||
resp = resp.click('Pricing')
|
||||
resp = resp.click('Criterias')
|
||||
resp = resp.click('New criteria category')
|
||||
resp.form['label'] = 'QF'
|
||||
resp = resp.form.submit()
|
||||
|
@ -39,10 +277,6 @@ def test_add_category(settings, app, admin_user):
|
|||
assert category.label == 'QF'
|
||||
assert category.slug == 'qf'
|
||||
|
||||
settings.CHRONO_ENABLE_PRICING = False
|
||||
resp = app.get('/manage/')
|
||||
assert 'Pricing' not in resp.text
|
||||
|
||||
|
||||
def test_add_category_as_manager(app, manager_user):
|
||||
app = login(app, username='manager', password='manager')
|
||||
|
@ -100,8 +334,7 @@ def test_add_criteria(app, admin_user):
|
|||
category = CriteriaCategory.objects.create(label='QF')
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/')
|
||||
resp = resp.click('Pricing')
|
||||
resp = app.get('/manage/pricing/criterias/')
|
||||
resp = resp.click('Add a criteria')
|
||||
resp.form['label'] = 'QF < 1'
|
||||
resp.form['condition'] = 'qf < 1 #'
|
||||
|
|
Loading…
Reference in New Issue