pricing: configuration of pricing models (#64903)

This commit is contained in:
Lauréline Guérin 2022-05-06 10:10:42 +02:00
parent 81722913a4
commit 306ec0e5ce
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
11 changed files with 673 additions and 17 deletions

View File

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

View File

@ -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 %}

View File

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

View File

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

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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/$',

View File

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

View File

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