Facturation: bouton et flag "finaliser la campagne" (#75560) #47
|
@ -206,3 +206,20 @@ def unlock_events_check(agenda_slugs, date_start, date_end):
|
|||
raise ChronoError(_('Unable to unlock events check'))
|
||||
if result.get('err'):
|
||||
raise ChronoError(_('Unable to unlock events check (%s)') % result['err_desc'])
|
||||
|
||||
|
||||
def mark_events_invoiced(agenda_slugs, date_start, date_end):
|
||||
result = chrono_json(
|
||||
'/api/agendas/events/invoiced/',
|
||||
json_params={
|
||||
'invoiced': True,
|
||||
'agendas': ','.join(agenda_slugs),
|
||||
'date_start': date_start.isoformat(),
|
||||
'date_end': date_end.isoformat(),
|
||||
},
|
||||
method='post',
|
||||
)
|
||||
if not result:
|
||||
raise ChronoError(_('Unable to mark events as invoiced'))
|
||||
if result.get('err'):
|
||||
raise ChronoError(_('Unable to mark events as invoiced (%s)') % result['err_desc'])
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('invoicing', '0023_campaign_dates'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='campaign',
|
||||
name='finalized',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
|
@ -147,6 +147,7 @@ class Campaign(models.Model):
|
|||
)
|
||||
agendas = models.ManyToManyField(Agenda, related_name='campaigns')
|
||||
invalid = models.BooleanField(default=False)
|
||||
finalized = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return _('%(label)s (%(start)s - %(end)s)') % {
|
||||
|
@ -164,6 +165,10 @@ class Campaign(models.Model):
|
|||
if commit:
|
||||
self.save()
|
||||
|
||||
def mark_as_finalized(self):
|
||||
self.finalized = True
|
||||
self.save()
|
||||
|
||||
def generate(self, spool=True):
|
||||
pool = self.pool_set.create(draft=True)
|
||||
try:
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
{% block appbar %}
|
||||
<h2>{{ object }}</h2>
|
||||
{% if not has_running_pool and not has_real_pool %}
|
||||
{% if not object.finalized and not has_running_pool and not has_real_pool %}
|
||||
<span class="actions">
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-delete' regie_pk=regie.pk pk=object.pk %}" rel="popup">{% trans "Delete" %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-edit' regie_pk=regie.pk pk=object.pk %}">{% trans "Edit" %}</a>
|
||||
|
@ -53,7 +53,7 @@
|
|||
<li>{% trans "Issue date:" %} {{ object.date_issue|date:'d/m/Y' }}</li>
|
||||
<li>{% trans "Debit date:" %} {{ object.date_debit|date:'d/m/Y' }}</li>
|
||||
</ul>
|
||||
{% if not has_running_pool %}
|
||||
{% if not object.finalized and not has_running_pool %}
|
||||
<div class="panel--buttons">
|
||||
<a class="pk-button" rel="popup" href="{% url 'lingo-manager-invoicing-campaign-dates-edit' regie_pk=regie.pk pk=object.pk %}">{% trans 'Edit' %}</a>
|
||||
</div>
|
||||
|
@ -81,13 +81,19 @@
|
|||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% if not has_running_pool and not has_real_pool %}
|
||||
<div class="panel--buttons">
|
||||
<a class="pk-button" rel="popup" href="{% url 'lingo-manager-invoicing-pool-add' regie_pk=regie.pk pk=object.pk %}">{% trans 'Start a pool' %}</a>
|
||||
{% if not object.invalid %}
|
||||
<a class="pk-button" rel="popup" href="{% url 'lingo-manager-invoicing-campaign-unlock-check' regie_pk=regie.pk pk=object.pk %}">{% trans 'Unlock check' %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if not object.finalized and not has_running_pool %}
|
||||
{% if not has_real_pool %}
|
||||
<div class="panel--buttons">
|
||||
<a class="pk-button" rel="popup" href="{% url 'lingo-manager-invoicing-pool-add' regie_pk=regie.pk pk=object.pk %}">{% trans 'Start a pool' %}</a>
|
||||
{% if not object.invalid %}
|
||||
<a class="pk-button" rel="popup" href="{% url 'lingo-manager-invoicing-campaign-unlock-check' regie_pk=regie.pk pk=object.pk %}">{% trans 'Unlock check' %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% elif has_real_completed_pool %}
|
||||
<div class="panel--buttons">
|
||||
<a class="pk-button" rel="popup" href="{% url 'lingo-manager-invoicing-campaign-finalize' regie_pk=regie.pk pk=object.pk %}">{% trans 'Finalize campaign' %}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
{% extends "lingo/invoicing/manager_campaign_detail.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-finalize' regie.pk object.pk %}">{% trans "Finalize campaign" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans "Finalize campaign" %}</h2>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<p>{% trans "Are you sure you want to finalize this campaign?" %}</p>
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Finalize campaign" %}</button>
|
||||
<a class="cancel" href="{% url 'lingo-manager-invoicing-campaign-detail' regie.pk object.pk %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
|
@ -15,11 +15,13 @@
|
|||
</h2>
|
||||
<span class="actions">
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-journal' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk %}">{% trans "Journal" %}</a>
|
||||
{% if not has_running_pool %}
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-delete' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk %}" rel="popup">{% trans "Delete" %}</a>
|
||||
{% endif %}
|
||||
{% if not object.invalid and pool.draft and pool.status == 'completed' and pool.is_last %}
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-promote' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk %}" rel="popup">{% trans "Promote" %}</a>
|
||||
{% if not object.finalized %}
|
||||
{% if not has_running_pool %}
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-delete' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk %}" rel="popup">{% trans "Delete" %}</a>
|
||||
{% endif %}
|
||||
{% if not object.invalid and pool.draft and pool.status == 'completed' and pool.is_last %}
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-promote' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk %}" rel="popup">{% trans "Promote" %}</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
|
|
@ -69,6 +69,9 @@
|
|||
<a href="{% url 'lingo-manager-invoicing-campaign-detail' regie_pk=regie.pk pk=campaign.pk %}">
|
||||
{{ campaign }}
|
||||
<span class="extra-info"> [{% trans "issue date:" %} {{ campaign.date_issue|date:'d/m/Y' }}]</span>
|
||||
{% if campaign.finalized %}
|
||||
<span class="badge">{% trans "finalized" %}</span>
|
||||
{% endif %}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
|
|
@ -73,6 +73,11 @@ urlpatterns = [
|
|||
views.campaign_unlock_check,
|
||||
name='lingo-manager-invoicing-campaign-unlock-check',
|
||||
),
|
||||
path(
|
||||
'regie/<int:regie_pk>/campaign/<int:pk>/finalize/',
|
||||
views.campaign_finalize,
|
||||
name='lingo-manager-invoicing-campaign-finalize',
|
||||
),
|
||||
path(
|
||||
'regie/<int:regie_pk>/campaign/<int:pk>/pool/add/',
|
||||
views.pool_add,
|
||||
|
|
|
@ -39,7 +39,7 @@ from django.views.generic import (
|
|||
)
|
||||
from weasyprint import HTML
|
||||
|
||||
from lingo.agendas.chrono import ChronoError, unlock_events_check
|
||||
from lingo.agendas.chrono import ChronoError, mark_events_invoiced, unlock_events_check
|
||||
from lingo.agendas.models import Agenda
|
||||
from lingo.invoicing.forms import (
|
||||
CampaignDatesForm,
|
||||
|
@ -288,6 +288,9 @@ class CampaignDetailView(DetailView):
|
|||
).order_by('-created_at')
|
||||
kwargs['has_running_pool'] = any(p.status in ['registered', 'running'] for p in kwargs['pools'])
|
||||
kwargs['has_real_pool'] = any(not p.draft for p in kwargs['pools'])
|
||||
kwargs['has_real_completed_pool'] = any(
|
||||
not p.draft and p.status == 'completed' for p in kwargs['pools']
|
||||
)
|
||||
if self.object.invalid:
|
||||
messages.warning(self.request, _('The last pool is invalid, please start a new pool.'))
|
||||
return super().get_context_data(**kwargs)
|
||||
|
@ -309,7 +312,7 @@ class CampaignEditView(UpdateView):
|
|||
return (
|
||||
super()
|
||||
.get_queryset()
|
||||
.filter(regie=self.regie)
|
||||
.filter(regie=self.regie, finalized=False)
|
||||
.exclude(pool__draft=False)
|
||||
.exclude(pool__status__in=['registered', 'running'])
|
||||
)
|
||||
|
@ -338,7 +341,7 @@ class CampaignDatesEditView(UpdateView):
|
|||
return (
|
||||
super()
|
||||
.get_queryset()
|
||||
.filter(regie=self.regie)
|
||||
.filter(regie=self.regie, finalized=False)
|
||||
.exclude(pool__status__in=['registered', 'running'])
|
||||
)
|
||||
|
||||
|
@ -367,7 +370,7 @@ class CampaignDeleteView(DeleteView):
|
|||
return (
|
||||
super()
|
||||
.get_queryset()
|
||||
.filter(regie=self.regie)
|
||||
.filter(regie=self.regie, finalized=False)
|
||||
.exclude(pool__draft=False)
|
||||
.exclude(pool__status__in=['registered', 'running'])
|
||||
)
|
||||
|
@ -392,7 +395,7 @@ class CampaignUnlockCheckView(FormView):
|
|||
def dispatch(self, request, *args, **kwargs):
|
||||
self.regie = get_object_or_404(Regie, pk=kwargs['regie_pk'])
|
||||
self.object = get_object_or_404(
|
||||
Campaign.objects.filter(regie=self.regie, invalid=False)
|
||||
Campaign.objects.filter(regie=self.regie, invalid=False, finalized=False)
|
||||
.exclude(pool__draft=False)
|
||||
.exclude(pool__status__in=['registered', 'running']),
|
||||
pk=kwargs['pk'],
|
||||
|
@ -427,6 +430,52 @@ class CampaignUnlockCheckView(FormView):
|
|||
campaign_unlock_check = CampaignUnlockCheckView.as_view()
|
||||
|
||||
|
||||
class CampaignFinalizeView(FormView):
|
||||
template_name = 'lingo/invoicing/manager_campaign_finalize.html'
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.regie = get_object_or_404(Regie, pk=kwargs['regie_pk'])
|
||||
self.object = get_object_or_404(
|
||||
Campaign.objects.filter(regie=self.regie, invalid=False, finalized=False).filter(
|
||||
pk__in=Pool.objects.filter(draft=False, status='completed').values('campaign')
|
||||
),
|
||||
pk=kwargs['pk'],
|
||||
)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['form'] = None
|
||||
kwargs['regie'] = self.regie
|
||||
kwargs['object'] = self.object
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
try:
|
||||
agendas = [a.slug for a in self.object.agendas.all()]
|
||||
if agendas:
|
||||
try:
|
||||
mark_events_invoiced(
|
||||
agenda_slugs=agendas,
|
||||
date_start=self.object.date_start,
|
||||
date_end=self.object.date_end,
|
||||
)
|
||||
except ChronoError as e:
|
||||
messages.error(self.request, _('Fail to mark events as invoiced: %s') % e)
|
||||
raise
|
||||
except ChronoError:
|
||||
pass
|
||||
else:
|
||||
self.object.mark_as_finalized()
|
||||
|
||||
return redirect(
|
||||
'%s#open:pools'
|
||||
% reverse('lingo-manager-invoicing-campaign-detail', args=[self.regie.pk, self.object.pk])
|
||||
)
|
||||
|
||||
|
||||
campaign_finalize = CampaignFinalizeView.as_view()
|
||||
|
||||
|
||||
class PoolDetailView(ListView):
|
||||
template_name = 'lingo/invoicing/manager_pool_detail.html'
|
||||
paginate_by = 100
|
||||
|
@ -520,7 +569,7 @@ class PoolAddView(FormView):
|
|||
def dispatch(self, request, *args, **kwargs):
|
||||
self.regie = get_object_or_404(Regie, pk=kwargs['regie_pk'])
|
||||
self.object = get_object_or_404(
|
||||
Campaign.objects.filter(regie=self.regie)
|
||||
Campaign.objects.filter(regie=self.regie, finalized=False)
|
||||
.exclude(pool__draft=False)
|
||||
.exclude(pool__status__in=['registered', 'running']),
|
||||
pk=kwargs['pk'],
|
||||
|
@ -555,6 +604,7 @@ class PoolPromoteView(FormView):
|
|||
campaign__id=kwargs['pk'],
|
||||
campaign__regie=self.regie,
|
||||
campaign__invalid=False,
|
||||
campaign__finalized=False,
|
||||
pk=kwargs['pool_pk'],
|
||||
draft=True,
|
||||
status='completed',
|
||||
|
@ -591,7 +641,9 @@ class PoolDeleteView(DeleteView):
|
|||
def dispatch(self, request, *args, **kwargs):
|
||||
self.regie = get_object_or_404(Regie, pk=kwargs['regie_pk'])
|
||||
self.campaign = get_object_or_404(
|
||||
Campaign.objects.filter(regie=self.regie).exclude(pool__status__in=['registered', 'running']),
|
||||
Campaign.objects.filter(regie=self.regie, finalized=False).exclude(
|
||||
pool__status__in=['registered', 'running']
|
||||
),
|
||||
pk=kwargs['pk'],
|
||||
)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
|
|
@ -14,6 +14,7 @@ from lingo.agendas.chrono import (
|
|||
get_events,
|
||||
get_subscriptions,
|
||||
lock_events_check,
|
||||
mark_events_invoiced,
|
||||
refresh_agendas,
|
||||
unlock_events_check,
|
||||
)
|
||||
|
@ -604,3 +605,75 @@ def test_unlock_events_check_status():
|
|||
'date_end': '2022-10-01',
|
||||
}
|
||||
assert requests_post.call_args_list[0][1]['remote_service']['url'] == 'http://chrono.example.org'
|
||||
|
||||
|
||||
def test_mark_events_invoiced_no_service(settings):
|
||||
settings.KNOWN_SERVICES = {}
|
||||
with pytest.raises(ChronoError) as e:
|
||||
mark_events_invoiced(
|
||||
agenda_slugs=['foo'],
|
||||
date_start=datetime.date(2022, 9, 1),
|
||||
date_end=datetime.date(2022, 10, 1),
|
||||
)
|
||||
assert str(e.value) == 'Unable to mark events as invoiced'
|
||||
|
||||
settings.KNOWN_SERVICES = {'other': []}
|
||||
with pytest.raises(ChronoError) as e:
|
||||
mark_events_invoiced(
|
||||
agenda_slugs=['foo'],
|
||||
date_start=datetime.date(2022, 9, 1),
|
||||
date_end=datetime.date(2022, 10, 1),
|
||||
)
|
||||
assert str(e.value) == 'Unable to mark events as invoiced'
|
||||
|
||||
|
||||
def test_mark_events_invoiced_status():
|
||||
with mock.patch('requests.Session.post') as requests_post:
|
||||
requests_post.side_effect = ConnectionError()
|
||||
with pytest.raises(ChronoError) as e:
|
||||
mark_events_invoiced(
|
||||
agenda_slugs=['foo', 'bar'],
|
||||
date_start=datetime.date(2022, 9, 1),
|
||||
date_end=datetime.date(2022, 10, 1),
|
||||
)
|
||||
assert str(e.value) == 'Unable to mark events as invoiced'
|
||||
|
||||
with mock.patch('requests.Session.post') as requests_post:
|
||||
mock_resp = Response()
|
||||
mock_resp.status_code = 500
|
||||
requests_post.return_value = mock_resp
|
||||
with pytest.raises(ChronoError) as e:
|
||||
mark_events_invoiced(
|
||||
agenda_slugs=['foo', 'bar'],
|
||||
date_start=datetime.date(2022, 9, 1),
|
||||
date_end=datetime.date(2022, 10, 1),
|
||||
)
|
||||
assert str(e.value) == 'Unable to mark events as invoiced'
|
||||
|
||||
with mock.patch('requests.Session.post') as requests_post:
|
||||
mock_resp = Response()
|
||||
mock_resp.status_code = 404
|
||||
requests_post.return_value = mock_resp
|
||||
with pytest.raises(ChronoError) as e:
|
||||
mark_events_invoiced(
|
||||
agenda_slugs=['foo', 'bar'],
|
||||
date_start=datetime.date(2022, 9, 1),
|
||||
date_end=datetime.date(2022, 10, 1),
|
||||
)
|
||||
assert str(e.value) == 'Unable to mark events as invoiced'
|
||||
|
||||
with mock.patch('requests.Session.post') as requests_post:
|
||||
requests_post.return_value = MockedRequestResponse(content=json.dumps({'foo': 'bar'}))
|
||||
mark_events_invoiced(
|
||||
agenda_slugs=['foo', 'bar'],
|
||||
date_start=datetime.date(2022, 9, 1),
|
||||
date_end=datetime.date(2022, 10, 1),
|
||||
)
|
||||
assert requests_post.call_args_list[0][0] == ('/api/agendas/events/invoiced/',)
|
||||
assert requests_post.call_args_list[0][1]['json'] == {
|
||||
'invoiced': True,
|
||||
'agendas': 'foo,bar',
|
||||
'date_start': '2022-09-01',
|
||||
'date_end': '2022-10-01',
|
||||
}
|
||||
assert requests_post.call_args_list[0][1]['remote_service']['url'] == 'http://chrono.example.org'
|
||||
|
|
|
@ -231,6 +231,7 @@ def test_detail_campaign(app, admin_user):
|
|||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool2.pk) in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk) not in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk) not in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) not in resp
|
||||
|
||||
pool2.status = 'running'
|
||||
pool2.save()
|
||||
|
@ -242,6 +243,7 @@ def test_detail_campaign(app, admin_user):
|
|||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool2.pk) in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk) not in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk) not in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) not in resp
|
||||
|
||||
pool2.status = 'failed'
|
||||
pool2.save()
|
||||
|
@ -253,6 +255,7 @@ def test_detail_campaign(app, admin_user):
|
|||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool2.pk) in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk) in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk) in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) not in resp
|
||||
|
||||
pool3 = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
|
@ -268,8 +271,15 @@ def test_detail_campaign(app, admin_user):
|
|||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool3.pk) in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk) not in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk) not in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) in resp
|
||||
assert 'The last pool is invalid, please start a new pool.' not in resp
|
||||
for status in ['running', 'failed', 'registered']:
|
||||
pool3.status = status
|
||||
pool3.save()
|
||||
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) not in resp
|
||||
|
||||
pool3.status = 'completed'
|
||||
pool3.draft = True
|
||||
pool3.save()
|
||||
campaign.invalid = True
|
||||
|
@ -283,8 +293,23 @@ def test_detail_campaign(app, admin_user):
|
|||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool3.pk) in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk) in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk) not in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) not in resp
|
||||
assert 'The last pool is invalid, please start a new pool.' in resp
|
||||
|
||||
campaign.invalid = False
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/' % (regie.pk, campaign.pk))
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk) not in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk) not in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk) not in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool1.pk) in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool2.pk) in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool3.pk) in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk) not in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk) not in resp
|
||||
assert '/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk) not in resp
|
||||
|
||||
line = DraftInvoiceLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=1,
|
||||
|
@ -413,6 +438,12 @@ def test_edit_campaign(app, admin_user):
|
|||
pool.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk), status=404)
|
||||
|
||||
pool.draft = True
|
||||
pool.save()
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk), status=404)
|
||||
|
||||
|
||||
def test_edit_campaign_overlapping_date_start(app, admin_user):
|
||||
regie = Regie.objects.create(label='Foo')
|
||||
|
@ -637,6 +668,14 @@ def test_edit_campaign_dates(app, admin_user):
|
|||
assert invoice2.date_issue == campaign.date_issue
|
||||
assert invoice2.date_debit == campaign.date_debit
|
||||
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk))
|
||||
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (0, campaign.pk), status=404)
|
||||
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk), status=404)
|
||||
|
||||
|
||||
def test_delete_campaign(app, admin_user):
|
||||
regie = Regie.objects.create(label='Foo')
|
||||
|
@ -753,6 +792,12 @@ def test_add_pool(app, admin_user):
|
|||
pool.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk), status=404)
|
||||
|
||||
pool.draft = True
|
||||
pool.save()
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/pool/add/' % (regie.pk, campaign.pk), status=404)
|
||||
|
||||
|
||||
@mock.patch('lingo.invoicing.views.unlock_events_check')
|
||||
def test_unlock_check(mock_unlock, app, admin_user):
|
||||
|
@ -843,6 +888,108 @@ def test_unlock_check(mock_unlock, app, admin_user):
|
|||
campaign.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk), status=404)
|
||||
|
||||
campaign.invalid = False
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/unlock-check/' % (regie.pk, campaign.pk), status=404)
|
||||
|
||||
|
||||
@mock.patch('lingo.invoicing.views.mark_events_invoiced')
|
||||
def test_finalize(mock_invoiced, app, admin_user):
|
||||
regie = Regie.objects.create(label='Foo')
|
||||
agenda = Agenda.objects.create(label='Foo bar', regie=regie)
|
||||
agenda2 = Agenda.objects.create(label='Foo bar 2', regie=regie)
|
||||
Agenda.objects.create(label='Foo bar 3', regie=regie)
|
||||
campaign = Campaign.objects.create(
|
||||
regie=regie,
|
||||
date_start=datetime.date(2022, 9, 1),
|
||||
date_end=datetime.date(2022, 10, 1),
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
date_payment_deadline=datetime.date(2022, 10, 31),
|
||||
date_issue=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
status='completed',
|
||||
)
|
||||
|
||||
app = login(app)
|
||||
|
||||
# no agendas
|
||||
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk))
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith(
|
||||
'/manage/invoicing/regie/%s/campaign/%s/#open:pools' % (regie.pk, campaign.pk)
|
||||
)
|
||||
assert mock_invoiced.call_args_list == []
|
||||
campaign.refresh_from_db()
|
||||
assert campaign.finalized is True
|
||||
|
||||
# with agendas
|
||||
campaign.finalized = False
|
||||
campaign.save()
|
||||
campaign.agendas.add(agenda, agenda2)
|
||||
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk))
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith(
|
||||
'/manage/invoicing/regie/%s/campaign/%s/#open:pools' % (regie.pk, campaign.pk)
|
||||
)
|
||||
assert mock_invoiced.call_args_list == [
|
||||
mock.call(
|
||||
agenda_slugs=['foo-bar', 'foo-bar-2'],
|
||||
date_start=datetime.date(2022, 9, 1),
|
||||
date_end=datetime.date(2022, 10, 1),
|
||||
)
|
||||
]
|
||||
campaign.refresh_from_db()
|
||||
assert campaign.finalized is True
|
||||
|
||||
# ChronoError
|
||||
campaign.finalized = False
|
||||
campaign.save()
|
||||
mock_invoiced.side_effect = ChronoError('foo baz')
|
||||
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk))
|
||||
resp = resp.form.submit().follow()
|
||||
assert 'Fail to mark events as invoiced: foo baz' in resp
|
||||
campaign.refresh_from_db()
|
||||
assert campaign.finalized is False
|
||||
|
||||
pool.status = 'failed'
|
||||
pool.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk), status=404)
|
||||
|
||||
pool.status = 'completed'
|
||||
pool.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk))
|
||||
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (0, campaign.pk), status=404)
|
||||
|
||||
pool.status = 'registered'
|
||||
pool.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk), status=404)
|
||||
|
||||
pool.status = 'running'
|
||||
pool.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk), status=404)
|
||||
|
||||
pool.status = 'completed'
|
||||
pool.draft = True
|
||||
pool.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk), status=404)
|
||||
|
||||
pool.draft = False
|
||||
pool.save()
|
||||
campaign.invalid = True
|
||||
campaign.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk), status=404)
|
||||
|
||||
campaign.invalid = False
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
app.get('/manage/invoicing/regie/%s/campaign/%s/finalize/' % (regie.pk, campaign.pk), status=404)
|
||||
|
||||
|
||||
def test_promote_pool(app, admin_user):
|
||||
regie = Regie.objects.create(label='Foo')
|
||||
|
@ -913,6 +1060,14 @@ def test_promote_pool(app, admin_user):
|
|||
)
|
||||
|
||||
campaign.invalid = False
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
app.get(
|
||||
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk),
|
||||
status=404,
|
||||
)
|
||||
|
||||
campaign.finalized = False
|
||||
campaign.save()
|
||||
resp = app.get(
|
||||
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk)
|
||||
|
@ -1021,6 +1176,19 @@ def test_detail_pool(app, admin_user):
|
|||
)
|
||||
|
||||
campaign.invalid = False
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/pool/%s/' % (regie.pk, campaign.pk, pool.pk))
|
||||
assert (
|
||||
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk)
|
||||
not in resp
|
||||
)
|
||||
assert (
|
||||
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/promote/' % (regie.pk, campaign.pk, pool.pk)
|
||||
not in resp
|
||||
)
|
||||
|
||||
campaign.finalized = False
|
||||
campaign.save()
|
||||
pool2 = Pool.objects.create(
|
||||
campaign=pool.campaign,
|
||||
|
@ -2360,6 +2528,15 @@ def test_delete_pool(app, admin_user):
|
|||
status=404,
|
||||
)
|
||||
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
app.get(
|
||||
'/manage/invoicing/regie/%s/campaign/%s/pool/%s/delete/' % (regie.pk, campaign.pk, pool.pk),
|
||||
status=404,
|
||||
)
|
||||
|
||||
campaign.finalized = False
|
||||
campaign.save()
|
||||
pool.draft = False
|
||||
pool.status = 'error'
|
||||
pool.save()
|
||||
|
|
|
@ -115,6 +115,31 @@ def test_manager_invoicing_regie_detail(app, admin_user):
|
|||
assert '/manage/pricing/agenda/%s/' % agenda2.pk in resp
|
||||
assert '/manage/pricing/agenda/%s/' % agenda3.pk not in resp
|
||||
|
||||
campaign = Campaign.objects.create(
|
||||
regie=regie,
|
||||
date_start=datetime.date(2022, 9, 1),
|
||||
date_end=datetime.date(2022, 10, 1),
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
date_payment_deadline=datetime.date(2022, 10, 31),
|
||||
date_issue=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
)
|
||||
resp = app.get(reverse('lingo-manager-invoicing-regie-detail', kwargs={'pk': regie.pk}))
|
||||
href = resp.pyquery(
|
||||
'div#panel-campaigns ul li a[href="%s"]'
|
||||
% reverse('lingo-manager-invoicing-campaign-detail', kwargs={'regie_pk': regie.pk, 'pk': campaign.pk})
|
||||
)
|
||||
assert href.text() == '(01/09/2022 - 01/10/2022) [issue date: 31/10/2022]'
|
||||
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
resp = app.get(reverse('lingo-manager-invoicing-regie-detail', kwargs={'pk': regie.pk}))
|
||||
href = resp.pyquery(
|
||||
'div#panel-campaigns ul li a[href="%s"]'
|
||||
% reverse('lingo-manager-invoicing-campaign-detail', kwargs={'regie_pk': regie.pk, 'pk': campaign.pk})
|
||||
)
|
||||
assert href.text() == '(01/09/2022 - 01/10/2022) [issue date: 31/10/2022] finalized'
|
||||
|
||||
|
||||
def test_manager_invoicing_regie_edit(app, admin_user):
|
||||
app = login(app)
|
||||
|
|
Loading…
Reference in New Issue