manager: configure invoicing options for partial bookings (#80842)
This commit is contained in:
parent
0fe3933ed1
commit
df0223abf2
|
@ -0,0 +1,33 @@
|
|||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('agendas', '0158_partial_booking_check_fields'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='agenda',
|
||||
name='invoicing_tolerance',
|
||||
field=models.PositiveSmallIntegerField(
|
||||
default=0, validators=[django.core.validators.MaxValueValidator(59)], verbose_name='Tolerance'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='agenda',
|
||||
name='invoicing_unit',
|
||||
field=models.CharField(
|
||||
choices=[
|
||||
('hour', 'Per hour'),
|
||||
('half_hour', 'Per half hour'),
|
||||
('quarter', 'Per quarter-hour'),
|
||||
('minute', 'Per minute'),
|
||||
],
|
||||
default='hour',
|
||||
max_length=10,
|
||||
verbose_name='Invoicing',
|
||||
),
|
||||
),
|
||||
]
|
|
@ -291,6 +291,22 @@ class Agenda(models.Model):
|
|||
blank=True,
|
||||
)
|
||||
partial_bookings = models.BooleanField(default=False)
|
||||
invoicing_unit = models.CharField(
|
||||
verbose_name=_('Invoicing'),
|
||||
max_length=10,
|
||||
choices=[
|
||||
('hour', _('Per hour')),
|
||||
('half_hour', _('Per half hour')),
|
||||
('quarter', _('Per quarter-hour')),
|
||||
('minute', _('Per minute')),
|
||||
],
|
||||
default='hour',
|
||||
)
|
||||
invoicing_tolerance = models.PositiveSmallIntegerField(
|
||||
verbose_name=_('Tolerance'),
|
||||
default=0,
|
||||
validators=[MaxValueValidator(59)],
|
||||
)
|
||||
|
||||
class Meta:
|
||||
ordering = ['label']
|
||||
|
|
|
@ -1538,6 +1538,15 @@ class AgendaBookingCheckSettingsForm(forms.ModelForm):
|
|||
widgets = {'booking_extra_user_block_template': forms.Textarea(attrs={'rows': 3})}
|
||||
|
||||
|
||||
class AgendaInvoicingSettingsForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Agenda
|
||||
fields = [
|
||||
'invoicing_unit',
|
||||
'invoicing_tolerance',
|
||||
]
|
||||
|
||||
|
||||
class AgendaNotificationsForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = AgendaNotificationsSettings
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
{% endif %}
|
||||
<button aria-controls="panel-display-options" aria-selected="false" id="tab-display-options" role="tab" tabindex="-1">{% trans "Display options" %}</button>
|
||||
<button aria-controls="panel-booking-check-options" aria-selected="false" id="tab-booking-check-options" role="tab" tabindex="-1">{% trans "Booking check options" %}</button>
|
||||
{% if agenda.partial_bookings %}
|
||||
<button aria-controls="panel-invoicing-options" aria-selected="false" id="tab-invoicing-options" role="tab" tabindex="-1">{% trans "Invoicing options" %}</button>
|
||||
{% endif %}
|
||||
<button aria-controls="panel-notifications" aria-selected="false" id="tab-notifications" role="tab" tabindex="-1">{% trans "Management notifications" %}</button>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -124,6 +127,18 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{% if agenda.partial_bookings %}
|
||||
<div aria-labelledby="tab-invoicing-options" hidden="" id="panel-invoicing-options" role="tabpanel" tabindex="0">
|
||||
<ul>
|
||||
<li>{% trans "Invoicing:" %} {{ agenda.get_invoicing_unit_display }}</li>
|
||||
<li>{% trans "Tolerance:" %} {% blocktrans count num=agenda.invoicing_tolerance %}{{ num }} minute{% plural %}{{ num }} minutes{% endblocktrans %}</li>
|
||||
</ul>
|
||||
<div class="panel--buttons">
|
||||
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-invoicing-settings' pk=object.pk %}">{% trans 'Configure' %}</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div aria-labelledby="tab-notifications" hidden="" id="panel-notifications" role="tabpanel" tabindex="0">
|
||||
{% for notification_type in object.notifications_settings.get_notification_types %}
|
||||
{% if forloop.first %}<ul>{% endif %}
|
||||
|
|
|
@ -170,6 +170,11 @@ urlpatterns = [
|
|||
views.agenda_booking_check_settings,
|
||||
name='chrono-manager-agenda-booking-check-settings',
|
||||
),
|
||||
path(
|
||||
'agendas/<int:pk>/invoicing-options',
|
||||
views.agenda_invoicing_settings,
|
||||
name='chrono-manager-agenda-invoicing-settings',
|
||||
),
|
||||
path('agendas/<int:pk>/delete', views.agenda_delete, name='chrono-manager-agenda-delete'),
|
||||
path('agendas/<int:pk>/export', views.agenda_export, name='chrono-manager-agenda-export'),
|
||||
path('agendas/<int:pk>/add-event', views.agenda_add_event, name='chrono-manager-agenda-add-event'),
|
||||
|
|
|
@ -98,6 +98,7 @@ from .forms import (
|
|||
AgendaDisplaySettingsForm,
|
||||
AgendaDuplicateForm,
|
||||
AgendaEditForm,
|
||||
AgendaInvoicingSettingsForm,
|
||||
AgendaNotificationsForm,
|
||||
AgendaReminderForm,
|
||||
AgendaReminderTestForm,
|
||||
|
@ -1163,6 +1164,18 @@ class AgendaBookingCheckSettingsView(AgendaEditView):
|
|||
agenda_booking_check_settings = AgendaBookingCheckSettingsView.as_view()
|
||||
|
||||
|
||||
class AgendaInvoicingSettingsView(AgendaEditView):
|
||||
form_class = AgendaInvoicingSettingsForm
|
||||
title = _('Configure invoicing options')
|
||||
tab_anchor = 'invoicing-options'
|
||||
|
||||
def set_agenda(self, **kwargs):
|
||||
self.agenda = get_object_or_404(Agenda, pk=kwargs.get('pk'), kind='events', partial_bookings=True)
|
||||
|
||||
|
||||
agenda_invoicing_settings = AgendaInvoicingSettingsView.as_view()
|
||||
|
||||
|
||||
class AgendaDeleteView(DeleteView):
|
||||
template_name = 'chrono/manager_confirm_delete.html'
|
||||
model = Agenda
|
||||
|
|
|
@ -36,6 +36,43 @@ def test_manager_partial_bookings_add_agenda(app, admin_user, settings):
|
|||
]
|
||||
|
||||
|
||||
def test_options_partial_bookings_invoicing_settings(app, admin_user):
|
||||
agenda = Agenda.objects.create(label='Foo bar', kind='events', partial_bookings=True)
|
||||
assert agenda.invoicing_unit == 'hour'
|
||||
assert agenda.invoicing_tolerance == 0
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
||||
resp = resp.click(href='/manage/agendas/%s/invoicing-options' % agenda.pk)
|
||||
assert resp.form['invoicing_unit'].options == [
|
||||
('hour', True, 'Per hour'),
|
||||
('half_hour', False, 'Per half hour'),
|
||||
('quarter', False, 'Per quarter-hour'),
|
||||
('minute', False, 'Per minute'),
|
||||
]
|
||||
resp.form['invoicing_unit'] = 'half_hour'
|
||||
resp.form['invoicing_tolerance'] = 10
|
||||
resp = resp.form.submit().follow()
|
||||
|
||||
agenda.refresh_from_db()
|
||||
assert agenda.invoicing_unit == 'half_hour'
|
||||
assert agenda.invoicing_tolerance == 10
|
||||
|
||||
# check kind
|
||||
agenda.partial_bookings = False
|
||||
agenda.save()
|
||||
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
||||
assert '/manage/agendas/%s/invoicing-options' % agenda.pk not in resp
|
||||
agenda.kind = 'meetings'
|
||||
agenda.save()
|
||||
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
||||
assert '/manage/agendas/%s/invoicing-options' % agenda.pk not in resp
|
||||
agenda.kind = 'virtual'
|
||||
agenda.save()
|
||||
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
||||
assert '/manage/agendas/%s/invoicing-options' % agenda.pk not in resp
|
||||
|
||||
|
||||
def test_manager_partial_bookings_add_event(app, admin_user):
|
||||
agenda = Agenda.objects.create(label='Foo bar', kind='events', partial_bookings=True)
|
||||
|
||||
|
|
Loading…
Reference in New Issue