Facturation: paramétrage des dates d'une campagne (#75561) #44

Merged
lguerin merged 6 commits from wip/75561-campaign-dates into main 2023-04-13 10:22:07 +02:00
15 changed files with 596 additions and 190 deletions

View File

@ -26,11 +26,10 @@ from lingo.invoicing.models import Campaign, DraftInvoice, DraftInvoiceLine, Inv
class CampaignForm(forms.ModelForm):
class Meta:
model = Campaign
fields = ['label', 'date_start', 'date_end', 'date_issue', 'injected_lines', 'agendas']
fields = ['label', 'date_start', 'date_end', 'injected_lines', 'agendas']
widgets = {
'date_start': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
'date_end': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
'date_issue': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
'agendas': MultiSelectWidget,
}
@ -65,6 +64,67 @@ class CampaignForm(forms.ModelForm):
return cleaned_data
def save(self):
super().save(commit=False)
if self.instance._state.adding:
# init date fields
self.instance.date_publication = self.instance.date_end
self.instance.date_payment_deadline = self.instance.date_end
self.instance.date_issue = self.instance.date_end
self.instance.date_debit = self.instance.date_end
elif self.instance.pool_set.exists():
self.instance.mark_as_invalid(commit=False)
self.instance.save()
self._save_m2m()
return self.instance
class CampaignDatesForm(forms.ModelForm):
class Meta:
model = Campaign
fields = ['date_publication', 'date_payment_deadline', 'date_issue', 'date_debit']
widgets = {
'date_publication': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
'date_payment_deadline': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
'date_issue': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
'date_debit': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'),
}
def clean(self):
cleaned_data = super().clean()
if (
pmarillonnet marked this conversation as resolved Outdated

Intuitivement on pourrait se dire qu’il faut le même genre de vérification de la cohérence / prévention anachronique sur date_debit en plus de ces trois autres champs, non ?

Intuitivement on pourrait se dire qu’il faut le même genre de vérification de la cohérence / prévention anachronique sur date_debit en plus de ces trois autres champs, non ?

peut-être, je ne sais pas, ça n'a pas été précisé lors du dernier eoday, contrairement à ces trois dates là. On pourra toujours ajouter une vérif plus tard ?

peut-être, je ne sais pas, ça n'a pas été précisé lors du dernier eoday, contrairement à ces trois dates là. On pourra toujours ajouter une vérif plus tard ?

Ok, on pourra demander lors du prochain eoday oui.

Ok, on pourra demander lors du prochain eoday oui.
'date_publication' in cleaned_data
and 'date_payment_deadline' in cleaned_data
and 'date_issue' in cleaned_data
):
if cleaned_data['date_publication'] > cleaned_data['date_payment_deadline']:
self.add_error(
'date_payment_deadline', _('Payment deadline must be greater than publication date.')
)
elif cleaned_data['date_payment_deadline'] > cleaned_data['date_issue']:
self.add_error('date_issue', _('Issue date must be greater than payment deadline.'))
return cleaned_data
def save(self):
super().save()
draft_invoice_qs = DraftInvoice.objects.filter(pool__campaign=self.instance)
invoice_qs = Invoice.objects.filter(pool__campaign=self.instance)
for qs in [draft_invoice_qs, invoice_qs]:
qs.update(
pmarillonnet marked this conversation as resolved Outdated

Pareil ici, pourquoi on exclut date_debit de la mise à jour des queryset ?

Pareil ici, pourquoi on exclut date_debit de la mise à jour des queryset ?

c'est fait juste en dessous, uniquement pour les factures en prélèvement auto (pas de date de prélèvement pour une facture qui n'est pas en prélèvement auto)

c'est fait juste en dessous, uniquement pour les factures en prélèvement auto (pas de date de prélèvement pour une facture qui n'est pas en prélèvement auto)

Oulà oui pardon, fatigue :)

Oulà oui pardon, fatigue :)
date_publication=self.instance.date_publication,
date_payment_deadline=self.instance.date_payment_deadline,
date_issue=self.instance.date_issue,
)
qs.filter(payer_direct_debit=True).update(date_debit=self.instance.date_debit)
return self.instance
class AbstractInvoiceFilterSet(django_filters.FilterSet):
# for Invoice

View File

@ -1,69 +0,0 @@
# lingo - payment and billing system
# Copyright (C) 2022 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import datetime
from django.core.management.base import BaseCommand, CommandError
from lingo.invoicing.models import Campaign, Regie
class Command(BaseCommand):
help = 'Generate invoicing for a period'
def add_arguments(self, parser):
parser.add_argument('date_start')
parser.add_argument('date_end')
parser.add_argument('regie_id')
parser.add_argument('--date-issue')
def handle(self, *args, **options):
try:
date_start = datetime.datetime.fromisoformat(options['date_start']).date()
except ValueError:
raise CommandError('Bad value "%s" for date_start' % options['date_start'])
try:
date_end = datetime.datetime.fromisoformat(options['date_end']).date()
except ValueError:
raise CommandError('Bad value "%s" for date_end' % options['date_end'])
try:
regie = Regie.objects.get(pk=options['regie_id'])
except Regie.DoesNotExist:
raise CommandError('Bad value "%s" for regie_id' % options['regie_id'])
if options.get('date_issue'):
try:
date_issue = datetime.datetime.fromisoformat(options['date_issue']).date()
except ValueError:
raise CommandError('Bad value "%s" for date_issue' % options['date_issue'])
else:
date_issue = date_end
try:
campaign = Campaign.objects.get(date_start=date_start, date_end=date_end, regie=regie)
except Campaign.DoesNotExist:
campaigns = Campaign.objects.filter(regie=regie).extra(
where=["(date_start, date_end) OVERLAPS (%s, %s)"], params=[date_start, date_end]
)
if campaigns.exists():
raise CommandError('Overlapping campaigns already exist')
campaign = Campaign.objects.create(
regie=regie, date_start=date_start, date_end=date_end, date_issue=date_issue
)
campaign.generate(spool=False)
self.stdout.write(
self.style.SUCCESS('Invoicing generation OK (start: %s, end: %s)' % (date_start, date_end))
)

View File

@ -0,0 +1,63 @@
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('invoicing', '0022_campaign_invalid'),
]
operations = [
migrations.AddField(
model_name='campaign',
name='date_debit',
field=models.DateField(default=django.utils.timezone.now, verbose_name='Debit date'),
preserve_default=False,
),
migrations.AddField(
model_name='campaign',
name='date_payment_deadline',
field=models.DateField(default=django.utils.timezone.now, verbose_name='Payment deadline'),
preserve_default=False,
),
migrations.AddField(
model_name='campaign',
name='date_publication',
field=models.DateField(default=django.utils.timezone.now, verbose_name='Publication date'),
preserve_default=False,
),
migrations.AddField(
model_name='draftinvoice',
name='date_debit',
field=models.DateField(null=True, verbose_name='Debit date'),
),
migrations.AddField(
model_name='draftinvoice',
name='date_payment_deadline',
field=models.DateField(default=django.utils.timezone.now, verbose_name='Payment deadline'),
preserve_default=False,
),
migrations.AddField(
model_name='draftinvoice',
name='date_publication',
field=models.DateField(default=django.utils.timezone.now, verbose_name='Publication date'),
preserve_default=False,
),
migrations.AddField(
model_name='invoice',
name='date_debit',
field=models.DateField(null=True, verbose_name='Debit date'),
),
migrations.AddField(
model_name='invoice',
name='date_payment_deadline',
field=models.DateField(default=django.utils.timezone.now, verbose_name='Payment deadline'),
preserve_default=False,
),
migrations.AddField(
model_name='invoice',
name='date_publication',
field=models.DateField(default=django.utils.timezone.now, verbose_name='Publication date'),
preserve_default=False,
),
]

View File

@ -131,7 +131,10 @@ class Campaign(models.Model):
regie = models.ForeignKey(Regie, on_delete=models.PROTECT)
date_start = models.DateField(_('Start date'))
date_end = models.DateField(_('End date'))
date_publication = models.DateField(_('Publication date'))
date_payment_deadline = models.DateField(_('Payment deadline'))
date_issue = models.DateField(_('Issue date'))
date_debit = models.DateField(_('Debit date'))
injected_lines = models.CharField(
_('Integrate injected lines'),
choices=[
@ -156,9 +159,10 @@ class Campaign(models.Model):
self.invalid = False
self.save()
def mark_as_invalid(self):
def mark_as_invalid(self, commit=True):
self.invalid = True
self.save()
if commit:
self.save()
def generate(self, spool=True):
pool = self.pool_set.create(draft=True)
@ -330,7 +334,10 @@ class Pool(models.Model):
class AbstractInvoice(models.Model):
label = models.CharField(_('Label'), max_length=300)
total_amount = models.DecimalField(max_digits=9, decimal_places=2, default=0)
date_publication = models.DateField(_('Publication date'))
date_payment_deadline = models.DateField(_('Payment deadline'))
date_issue = models.DateField(_('Issue date'))
date_debit = models.DateField(_('Debit date'), null=True)
pmarillonnet marked this conversation as resolved Outdated

Pas compris dans le code ce qui justifie que seul ce champ de date de débit, et pour le modèle AbstractInvoice seulement, est nullable :(

Pas compris dans le code ce qui justifie que seul ce champ de date de débit, et pour le modèle AbstractInvoice seulement, est nullable :(

parce que pas de date de prélèvement si direct_debit = False :)

parce que pas de date de prélèvement si direct_debit = False :)

Ok mais je ne comprends pas fonctionnellement ce que ça veut dire que ce champ est nullable alors que le champ similaire date_debit sur une campagne ne l’est pas, et est en default=now à la place.

Ok mais je ne comprends pas fonctionnellement ce que ça veut dire que ce champ est nullable alors que le champ similaire `date_debit` sur une campagne ne l’est pas, et est en `default=now` à la place.

Le default sur Campaign c'était surtout pour gérer la migration; dans le formulaire de création d'une campagne, on initialise ces dates à date_end (la date de fin de la campagne qui vient d'être saisie).
date_debit n'est pas nullable sur une campagne car il nous faut définir une valeur à reporter sur les factures en prélèvement auto.

Pour une facture donnée, cette date de débit est vraiment nulle si payer_direct_debit est False: pas de prélèvement auto, donc pas de date de prélèvement.

Je m'étais posée la question de ne pas reporter ces dates sur les factures et plutôt aller les chercher sur la campagne liée. Mais je dois ajouter plus tard de quoi créer des factures hors campagne (cas du parent qui vient au guichet pour réserver le séjour au ski, le paie toute de suite, et repart avec une facture acquittée), donc dans le doute j'ai laissé le report des dates de campagne à facture. En me disant que du code, ça peut se refactorer.

Le default sur Campaign c'était surtout pour gérer la migration; dans le formulaire de création d'une campagne, on initialise ces dates à date_end (la date de fin de la campagne qui vient d'être saisie). date_debit n'est pas nullable sur une campagne car il nous faut définir une valeur à reporter sur les factures en prélèvement auto. Pour une facture donnée, cette date de débit est vraiment nulle si payer_direct_debit est False: pas de prélèvement auto, donc pas de date de prélèvement. Je m'étais posée la question de ne pas reporter ces dates sur les factures et plutôt aller les chercher sur la campagne liée. Mais je dois ajouter plus tard de quoi créer des factures hors campagne (cas du parent qui vient au guichet pour réserver le séjour au ski, le paie toute de suite, et repart avec une facture acquittée), donc dans le doute j'ai laissé le report des dates de campagne à facture. En me disant que du code, ça peut se refactorer.

Ok, ça fait sens, je comprends mieux, merci pour l’explication.

Ok, ça fait sens, je comprends mieux, merci pour l’explication.
regie = models.ForeignKey(Regie, on_delete=models.PROTECT)
payer_external_id = models.CharField(max_length=250)
payer_first_name = models.CharField(max_length=250)

View File

@ -0,0 +1,37 @@
{% extends "lingo/invoicing/manager_regie_detail.html" %}
{% load static i18n %}
{% block css %}
{{ block.super }}
<link rel="stylesheet" type="text/css" media="all" href="{% static "css/gadjo.multiselectwidget.css" %}" />
{% endblock %}
{% block extrascripts %}
{{ block.super }}
<script src="{% static "js/gadjo.multiselectwidget.js" %}"></script>
{% endblock %}
{% block breadcrumb %}
{{ block.super }}
<a href="{% url 'lingo-manager-invoicing-campaign-detail' regie.pk object.pk %}">{{ object.label }}</a>
pmarillonnet marked this conversation as resolved Outdated

Niveau UI, sur cette page où on édite des dates, avoir un lien vers la campagne juste présenté avec {{ object }} ça va faire label (date de début - date de fin). J’ai peur que ça fasse trop de dates et qu’on perde des gens en cours de route. Peut-être qu’on pourrait simplement mettre {{ object.label }} ?

Niveau UI, sur cette page où on édite des dates, avoir un lien vers la campagne juste présenté avec `{{ object }}` ça va faire `label (date de début - date de fin)`. J’ai peur que ça fasse trop de dates et qu’on perde des gens en cours de route. Peut-être qu’on pourrait simplement mettre `{{ object.label }}` ?

c'est dans une popup, donc on ne voit pas le breadcrumb (sauf si validation du form+errors), mais tu as raison, je vais modifier ça

c'est dans une popup, donc on ne voit pas le breadcrumb (sauf si validation du form+errors), mais tu as raison, je vais modifier ça

D’ac, merci.

D’ac, merci.
<a href="{% url 'lingo-manager-invoicing-campaign-dates-edit' regie.pk object.pk %}">{% trans "Edit dates" %}</a>
{% endblock %}
{% block appbar %}
<h2>{% trans "Edit dates" %}</h2>
{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<div class="buttons">
<button class="submit-button">{% trans "Save" %}</button>
{% if object.pk %}
<a class="cancel" href="{% url 'lingo-manager-invoicing-campaign-detail' regie.pk object.pk %}">{% trans 'Cancel' %}</a>
{% else %}
<a class="cancel" href="{% url 'lingo-manager-invoicing-regie-detail' regie.pk %}">{% trans 'Cancel' %}</a>
{% endif %}
</div>
</form>
{% endblock %}

View File

@ -3,7 +3,7 @@
{% block breadcrumb %}
{{ block.super }}
<a href="{% url 'lingo-manager-invoicing-campaign-detail' regie.pk object.pk %}">{{ object }}</a>
<a href="{% url 'lingo-manager-invoicing-campaign-detail' regie.pk object.pk %}">{{ object.label }}</a>
{% endblock %}
{% block appbar %}
@ -21,6 +21,7 @@
<div class="pk-tabs">
<div class="pk-tabs--tab-list" role="tablist">
<button aria-controls="panel-settings" aria-selected="true" id="tab-settings" role="tab" tabindex="0">{% trans "Settings" %}</button>
<button aria-controls="panel-dates" aria-selected="false" id="tab-dates" role="tab" tabindex="-1">{% trans "Dates" %}</button>
<button aria-controls="panel-pools" aria-selected="false" id="tab-pools" role="tab" tabindex="-1">{% trans "Pools" %}</button>
</div>
<div class="pk-tabs--container">
@ -30,7 +31,6 @@
<li>{% trans "Label:" %} {{ object.label }}</li>
<li>{% trans "Start date:" %} {{ object.date_start|date:'d/m/Y' }}</li>
<li>{% trans "End date:" %} {{ object.date_end|date:'d/m/Y' }}</li>
<li>{% trans "Issue date:" %} {{ object.date_issue|date:'d/m/Y' }}</li>
<li>{% trans "Integrate injected lines:" %} {{ object.get_injected_lines_display }}</li>
<li>{% trans "Agendas:" %}
<ul>
@ -46,6 +46,20 @@
</ul>
</div>
<div aria-labelledby="tab-dates" hidden="" id="panel-dates" role="tabpanel" tabindex="0">
<ul>
<li>{% trans "Publication date:" %} {{ object.date_publication|date:'d/m/Y' }}</li>
<li>{% trans "Payment deadline:" %} {{ object.date_payment_deadline|date:'d/m/Y' }}</li>
<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 %}
<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>
{% endif %}
</div>
<div aria-labelledby="tab-pools" hidden="" id="panel-pools" role="tabpanel" tabindex="0">
<ul class="objects-list single-links">
{% for pool in pools %}

View File

@ -58,6 +58,11 @@ urlpatterns = [
views.campaign_edit,
name='lingo-manager-invoicing-campaign-edit',
),
path(
'regie/<int:regie_pk>/campaign/<int:pk>/dates/edit/',
views.campaign_dates_edit,
name='lingo-manager-invoicing-campaign-dates-edit',
),
path(
'regie/<int:regie_pk>/campaign/<int:pk>/delete/',
views.campaign_delete,

View File

@ -292,7 +292,10 @@ def generate_invoices_from_lines(all_lines, pool):
'start': pool.campaign.date_start,
'end': pool.campaign.date_end - datetime.timedelta(days=1),
},
date_publication=pool.campaign.date_publication,
date_payment_deadline=pool.campaign.date_payment_deadline,
date_issue=pool.campaign.date_issue,
date_debit=pool.campaign.date_debit if payer_data['payer_direct_debit'] else None,
regie=regie,
payer_external_id=payer_external_id,
payer_first_name=payer_data['payer_first_name'],

View File

@ -40,6 +40,7 @@ from django.views.generic import (
from lingo.agendas.chrono import ChronoError, unlock_events_check
from lingo.agendas.models import Agenda
from lingo.invoicing.forms import (
CampaignDatesForm,
CampaignForm,
DraftInvoiceFilterSet,
DraftInvoiceLineFilterSet,
@ -322,6 +323,36 @@ class CampaignEditView(UpdateView):
campaign_edit = CampaignEditView.as_view()
class CampaignDatesEditView(UpdateView):
template_name = 'lingo/invoicing/manager_campaign_dates_form.html'
model = Campaign
form_class = CampaignDatesForm
def dispatch(self, request, *args, **kwargs):
self.regie = get_object_or_404(Regie, pk=kwargs['regie_pk'])
return super().dispatch(request, *args, **kwargs)
def get_queryset(self):
return (
super()
.get_queryset()
.filter(regie=self.regie)
.exclude(pool__status__in=['registered', 'running'])
)
def get_context_data(self, **kwargs):
kwargs['regie'] = self.regie
return super().get_context_data(**kwargs)
def get_success_url(self):
return '%s#open:dates' % reverse(
'lingo-manager-invoicing-campaign-detail', args=[self.regie.pk, self.object.pk]
)
campaign_dates_edit = CampaignDatesEditView.as_view()
class CampaignDeleteView(DeleteView):
template_name = 'lingo/manager_confirm_delete.html'
model = Campaign

View File

@ -30,7 +30,10 @@ def test_add_campaign(app, admin_user):
regie=other_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),
)
app = login(app)
@ -42,7 +45,6 @@ def test_add_campaign(app, admin_user):
resp.form['label'] = 'Foo'
resp.form['date_start'] = '2022-09-01'
resp.form['date_end'] = '2022-08-01'
resp.form['date_issue'] = '2022-10-31'
resp.form.get('agendas', 0).value = agenda.pk
assert resp.form['agendas'].options == [(str(agenda.pk), False, 'Foo bar')]
resp = resp.form.submit()
@ -55,7 +57,10 @@ def test_add_campaign(app, admin_user):
assert campaign.label == 'Foo'
assert campaign.date_start == datetime.date(2022, 9, 1)
assert campaign.date_end == datetime.date(2022, 10, 1)
assert campaign.date_issue == datetime.date(2022, 10, 31)
assert campaign.date_publication == campaign.date_end
assert campaign.date_payment_deadline == campaign.date_end
assert campaign.date_issue == campaign.date_end
assert campaign.date_debit == campaign.date_end
assert list(campaign.agendas.all()) == [agenda]
@ -69,7 +74,10 @@ def test_add_campaign_overlapping_date_start(app, admin_user):
label='Campaign',
date_start=datetime.date(2022, 9, 15),
date_end=datetime.date(2022, 10, 15),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
campaign.agendas.add(agenda1, agenda2)
@ -85,7 +93,6 @@ def test_add_campaign_overlapping_date_start(app, admin_user):
resp.form['label'] = 'Foo'
resp.form['date_start'] = '2022-10-01'
resp.form['date_end'] = '2022-11-01'
resp.form['date_issue'] = '2022-11-30'
resp.form.get('agendas', 0).value = agenda1.pk
resp.form.get('agendas', 1).value = agenda2.pk
resp = resp.form.submit()
@ -105,7 +112,6 @@ def test_add_campaign_overlapping_date_start(app, admin_user):
resp.form['label'] = 'Foo'
resp.form['date_start'] = '2021-10-01'
resp.form['date_end'] = '2022-11-01'
resp.form['date_issue'] = '2022-11-30'
resp.form.get('agendas', 0).value = agenda1.pk
resp.form.get('agendas', 1).value = agenda2.pk
resp = resp.form.submit()
@ -135,7 +141,10 @@ def test_add_campaign_overlapping_date_end(app, admin_user):
label='Campaign',
date_start=datetime.date(2022, 10, 15),
date_end=datetime.date(2022, 11, 15),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
campaign.agendas.add(agenda1, agenda2)
@ -151,7 +160,6 @@ def test_add_campaign_overlapping_date_end(app, admin_user):
resp.form['label'] = 'Foo'
resp.form['date_start'] = '2022-10-01'
resp.form['date_end'] = '2022-11-01'
resp.form['date_issue'] = '2022-11-30'
resp.form.get('agendas', 0).value = agenda1.pk
resp.form.get('agendas', 1).value = agenda2.pk
resp = resp.form.submit()
@ -171,7 +179,6 @@ def test_add_campaign_overlapping_date_end(app, admin_user):
resp.form['label'] = 'Foo'
resp.form['date_start'] = '2022-10-01'
resp.form['date_end'] = '2022-11-01'
resp.form['date_issue'] = '2022-11-30'
resp.form.get('agendas', 0).value = agenda1.pk
resp.form.get('agendas', 1).value = agenda2.pk
resp = resp.form.submit()
@ -197,7 +204,10 @@ def test_detail_campaign(app, admin_user):
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),
)
pool1 = Pool.objects.create(
campaign=campaign,
@ -213,6 +223,7 @@ def test_detail_campaign(app, admin_user):
app = login(app)
resp = app.get(url='/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
@ -223,6 +234,7 @@ def test_detail_campaign(app, admin_user):
pool2.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
@ -233,6 +245,7 @@ def test_detail_campaign(app, admin_user):
pool2.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) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk) 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
@ -246,6 +259,7 @@ def test_detail_campaign(app, admin_user):
)
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) 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
@ -260,6 +274,7 @@ def test_detail_campaign(app, admin_user):
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) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk) in resp
assert '/manage/invoicing/regie/%s/campaign/%s/delete/' % (regie.pk, campaign.pk) 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
@ -346,7 +361,10 @@ def test_edit_campaign(app, admin_user):
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),
)
app = login(app)
@ -354,7 +372,6 @@ def test_edit_campaign(app, admin_user):
resp.form['label'] = 'Bar'
resp.form['date_start'] = '2022-09-30'
resp.form['date_end'] = '2022-08-01'
resp.form['date_issue'] = '2022-12-31'
resp.form.get('agendas', 0).value = agenda.pk
resp = resp.form.submit()
assert resp.context['form'].errors['date_end'] == ['End date must be greater than start date.']
@ -363,14 +380,17 @@ def test_edit_campaign(app, admin_user):
campaign.refresh_from_db()
assert campaign.date_start == datetime.date(2022, 9, 30)
assert campaign.date_end == datetime.date(2022, 10, 2)
assert campaign.date_issue == datetime.date(2022, 12, 31)
assert campaign.invalid is False
pool = Pool.objects.create(
campaign=campaign,
draft=True,
status='completed',
)
app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk))
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/edit/' % (regie.pk, campaign.pk))
resp = resp.form.submit()
campaign.refresh_from_db()
assert campaign.invalid is True
pool.status = 'failed'
pool.save()
@ -402,7 +422,10 @@ def test_edit_campaign_overlapping_date_start(app, admin_user):
label='Campaign',
date_start=datetime.date(2022, 10, 1),
date_end=datetime.date(2022, 11, 1),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
campaign1.agendas.add(agenda1, agenda2)
campaign2 = Campaign.objects.create(
@ -410,7 +433,10 @@ def test_edit_campaign_overlapping_date_start(app, admin_user):
label='Campaign',
date_start=datetime.date(2022, 9, 15),
date_end=datetime.date(2022, 10, 15),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
campaign2.agendas.add(agenda1, agenda2)
@ -454,7 +480,10 @@ def test_edit_campaign_overlapping_date_end(app, admin_user):
label='Campaign',
date_start=datetime.date(2022, 10, 1),
date_end=datetime.date(2022, 11, 1),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
campaign1.agendas.add(agenda1, agenda2)
campaign2 = Campaign.objects.create(
@ -462,7 +491,10 @@ def test_edit_campaign_overlapping_date_end(app, admin_user):
label='Campaign',
date_start=datetime.date(2022, 10, 15),
date_end=datetime.date(2022, 11, 15),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
campaign2.agendas.add(agenda1, agenda2)
@ -496,13 +528,124 @@ def test_edit_campaign_overlapping_date_end(app, admin_user):
assert list(campaign1.agendas.all()) == [agenda3]
def test_edit_campaign_dates(app, admin_user):
regie = Regie.objects.create(label='Foo')
agenda = Agenda.objects.create(label='Foo bar', 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),
)
campaign.agendas.add(agenda)
pool1 = Pool.objects.create(
campaign=campaign,
draft=True,
status='completed',
)
draft_invoice1 = DraftInvoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool1,
)
draft_invoice2 = DraftInvoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
date_debit=campaign.date_debit,
regie=regie,
pool=pool1,
payer_direct_debit=True,
)
pool2 = Pool.objects.create(
campaign=campaign,
draft=False,
status='completed',
)
invoice1 = Invoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool2,
)
invoice2 = Invoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
date_debit=campaign.date_debit,
regie=regie,
pool=pool2,
payer_direct_debit=True,
)
app = login(app)
resp = app.get('/manage/invoicing/regie/%s/campaign/%s/dates/edit/' % (regie.pk, campaign.pk))
resp.form['date_publication'] = '2022-10-31'
resp.form['date_payment_deadline'] = '2022-10-30'
resp.form['date_issue'] = '2022-10-29'
resp.form['date_debit'] = '2022-12-15'
resp = resp.form.submit()
assert resp.context['form'].errors == {
'date_payment_deadline': ['Payment deadline must be greater than publication date.']
}
resp.form['date_publication'] = '2022-10-30'
resp.form['date_payment_deadline'] = '2022-10-31'
resp = resp.form.submit()
assert resp.context['form'].errors == {
'date_issue': ['Issue date must be greater than payment deadline.']
}
resp.form['date_publication'] = '2022-10-29'
resp.form['date_payment_deadline'] = '2022-10-30'
resp.form['date_issue'] = '2022-10-31'
resp.form.submit().follow()
campaign.refresh_from_db()
assert campaign.date_publication == datetime.date(2022, 10, 29)
assert campaign.date_payment_deadline == datetime.date(2022, 10, 30)
assert campaign.date_issue == datetime.date(2022, 10, 31)
assert campaign.date_debit == datetime.date(2022, 12, 15)
assert campaign.invalid is False # no impact
draft_invoice1.refresh_from_db()
assert draft_invoice1.date_publication == campaign.date_publication
assert draft_invoice1.date_payment_deadline == campaign.date_payment_deadline
assert draft_invoice1.date_issue == campaign.date_issue
assert draft_invoice1.date_debit is None
draft_invoice2.refresh_from_db()
assert draft_invoice2.date_publication == campaign.date_publication
assert draft_invoice2.date_payment_deadline == campaign.date_payment_deadline
assert draft_invoice2.date_issue == campaign.date_issue
assert draft_invoice2.date_debit == campaign.date_debit
invoice1.refresh_from_db()
assert invoice1.date_publication == campaign.date_publication
assert invoice1.date_payment_deadline == campaign.date_payment_deadline
assert invoice1.date_issue == campaign.date_issue
assert invoice1.date_debit is None
invoice2.refresh_from_db()
assert invoice2.date_publication == campaign.date_publication
assert invoice2.date_payment_deadline == campaign.date_payment_deadline
assert invoice2.date_issue == campaign.date_issue
assert invoice2.date_debit == campaign.date_debit
def test_delete_campaign(app, admin_user):
regie = Regie.objects.create(label='Foo')
campaign = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 10, 1),
date_issue=datetime.date(2022, 10, 31),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
app = login(app)
@ -517,7 +660,13 @@ def test_delete_campaign(app, admin_user):
draft=True,
status='completed',
)
invoice = DraftInvoice.objects.create(date_issue=datetime.date.today(), regie=regie, pool=pool)
invoice = DraftInvoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
)
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice,
@ -558,7 +707,10 @@ def test_add_pool(app, admin_user):
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),
invalid=True,
)
@ -610,7 +762,10 @@ def test_unlock_check(mock_unlock, app, admin_user):
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),
)
app = login(app)
@ -693,7 +848,10 @@ def test_promote_pool(app, admin_user):
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,
@ -774,13 +932,19 @@ def test_detail_pool(app, admin_user):
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),
)
campaign2 = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 10, 1),
date_end=datetime.date(2022, 11, 1),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
pool = Pool.objects.create(
campaign=campaign,
@ -934,7 +1098,10 @@ def test_detail_pool_invoices(app, admin_user, draft):
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,
@ -942,7 +1109,9 @@ def test_detail_pool_invoices(app, admin_user, draft):
status='completed',
)
invoice1 = invoice_model.objects.create(
date_issue=datetime.date.today(),
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
payer_external_id='payer:1',
@ -952,7 +1121,9 @@ def test_detail_pool_invoices(app, admin_user, draft):
payer_direct_debit=False,
)
invoice2 = invoice_model.objects.create(
date_issue=datetime.date.today(),
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
payer_external_id='payer:2',
@ -1194,13 +1365,19 @@ def test_journal_pool(app, admin_user):
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),
)
campaign2 = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 10, 1),
date_end=datetime.date(2022, 11, 1),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
pool = Pool.objects.create(
campaign=campaign,
@ -1358,7 +1535,10 @@ def test_journal_pool_lines(app, admin_user, draft):
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,
@ -1366,10 +1546,20 @@ def test_journal_pool_lines(app, admin_user, draft):
status='completed',
)
invoice1 = invoice_model.objects.create(
date_issue=datetime.date.today(), regie=regie, pool=pool, payer_external_id='payer:1'
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
payer_external_id='payer:1',
)
invoice2 = invoice_model.objects.create(
date_issue=datetime.date.today(), regie=regie, pool=pool, payer_external_id='payer:2'
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
payer_external_id='payer:2',
)
if not draft:
invoice1.set_number()
@ -1849,7 +2039,10 @@ def test_journal_pool_lines_link(settings, app, admin_user, draft):
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,
@ -1904,20 +2097,32 @@ def test_delete_pool(app, admin_user):
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),
)
campaign2 = Campaign.objects.create(
regie=regie,
date_start=datetime.date(2022, 10, 1),
date_end=datetime.date(2022, 11, 1),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
)
pool = Pool.objects.create(
campaign=campaign,
draft=True,
status='completed',
)
invoice = DraftInvoice.objects.create(date_issue=datetime.date.today(), regie=regie, pool=pool)
invoice = DraftInvoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
)
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice,
@ -1985,7 +2190,13 @@ def test_delete_pool(app, admin_user):
pool.draft = False
pool.status = 'error'
pool.save()
invoice = Invoice.objects.create(date_issue=datetime.date.today(), regie=regie, pool=pool)
invoice = Invoice.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
)
InvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
invoice=invoice,
@ -2014,7 +2225,10 @@ def test_set_error_status_line(app, admin_user):
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,

View File

@ -154,7 +154,10 @@ def test_manager_invoicing_regie_delete(app, admin_user):
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}))
assert reverse('lingo-manager-invoicing-regie-delete', kwargs={'pk': regie.pk}) not in resp
@ -216,7 +219,10 @@ def test_non_invoiced_line_list(app, admin_user):
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,
@ -226,7 +232,10 @@ def test_non_invoiced_line_list(app, admin_user):
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),
)
pool2 = Pool.objects.create(
campaign=campaign2,
@ -237,7 +246,10 @@ def test_non_invoiced_line_list(app, admin_user):
regie=other_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),
)
other_pool = Pool.objects.create(
campaign=other_campaign,
@ -247,7 +259,10 @@ def test_non_invoiced_line_list(app, admin_user):
regie=other_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),
)
other_pool2 = Pool.objects.create(
campaign=other_campaign2,
@ -435,7 +450,10 @@ def test_non_invoiced_line_link(app, admin_user, settings):
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,
@ -484,7 +502,10 @@ def test_regie_invoices(app, admin_user):
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),
)
pool1 = Pool.objects.create(
campaign=campaign1,
@ -495,7 +516,10 @@ def test_regie_invoices(app, admin_user):
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),
)
pool2 = Pool.objects.create(
campaign=campaign2,
@ -503,7 +527,9 @@ def test_regie_invoices(app, admin_user):
status='completed',
)
invoice1 = Invoice.objects.create(
date_issue=datetime.date.today(),
date_publication=campaign1.date_publication,
date_payment_deadline=campaign1.date_payment_deadline,
date_issue=campaign1.date_issue,
regie=regie,
pool=pool1,
payer_external_id='payer:1',
@ -515,7 +541,10 @@ def test_regie_invoices(app, admin_user):
invoice1.set_number()
invoice1.save()
invoice2 = Invoice.objects.create(
date_issue=datetime.date.today(),
date_publication=campaign2.date_publication,
date_payment_deadline=campaign2.date_payment_deadline,
date_issue=campaign2.date_issue,
date_debit=campaign2.date_debit,
regie=regie,
pool=pool2,
payer_external_id='payer:2',

View File

@ -3,7 +3,6 @@ import decimal
from unittest import mock
import pytest
from django.core.management import CommandError, call_command
from django.db import connection
from django.test.utils import CaptureQueriesContext
from django.utils.timezone import now
@ -47,7 +46,10 @@ def test_get_agendas():
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),
)
campaign.agendas.add(agenda1, agenda2, agenda3)
pool = Pool.objects.create(
@ -120,7 +122,10 @@ def test_get_users_from_subscriptions_error(mock_subscriptions):
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,
@ -140,7 +145,10 @@ def test_get_users_from_subscriptions(mock_subscriptions):
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,
@ -221,7 +229,10 @@ def test_get_invoice_lines_for_user_check_status_error(mock_status):
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,
@ -262,7 +273,10 @@ def test_get_invoice_lines_for_user_check_status(
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),
injected_lines=injected_lines,
)
old_pool = Pool.objects.create(
@ -277,7 +291,10 @@ def test_get_invoice_lines_for_user_check_status(
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),
)
other_pool = Pool.objects.create(
campaign=other_campaign,
@ -766,7 +783,10 @@ def test_get_invoice_lines_for_user_get_payer_id_error(mock_payer, mock_status):
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,
@ -839,7 +859,10 @@ def test_get_invoice_lines_for_user_get_payer_data_error(mock_payer_data, mock_p
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,
@ -914,7 +937,10 @@ def test_get_invoice_lines_for_user_get_payer_id_and_data(mock_status):
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),
injected_lines='all',
)
pool = Pool.objects.create(
@ -1154,7 +1180,10 @@ def test_get_invoice_lines_for_user_check_status_agenda_pricing_dates(mock_payer
regie=regie,
date_start=datetime.date(2022, 1, 1),
date_end=datetime.date(2023, 1, 1),
date_publication=datetime.date(2023, 1, 1),
date_payment_deadline=datetime.date(2023, 1, 31),
date_issue=datetime.date(2023, 1, 31),
date_debit=datetime.date(2022, 2, 15),
)
pool = Pool.objects.create(
campaign=campaign,
@ -1313,7 +1342,10 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(
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,
@ -1463,7 +1495,10 @@ def test_get_all_invoice_lines(mock_user_lines):
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,
@ -1585,7 +1620,10 @@ def test_get_all_invoice_lines_queryset(mock_payer_data, mock_payer, mock_status
regie=regie,
date_start=datetime.date(2022, 9, 1),
date_end=datetime.date(2022, 11, 1),
date_publication=datetime.date(2022, 11, 1),
date_payment_deadline=datetime.date(2022, 11, 30),
date_issue=datetime.date(2022, 11, 30),
date_debit=datetime.date(2022, 12, 15),
injected_lines='all',
)
pool = Pool.objects.create(
@ -1660,7 +1698,10 @@ def test_generate_invoices_from_lines():
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,
@ -1815,7 +1856,10 @@ def test_generate_invoices_from_lines():
assert isinstance(invoice1, DraftInvoice)
assert invoice1.label == 'Invoice from 2022-09-01 to 2022-09-30'
assert invoice1.total_amount == 18
assert invoice1.date_publication == datetime.date(2022, 10, 1)
assert invoice1.date_payment_deadline == datetime.date(2022, 10, 31)
assert invoice1.date_issue == datetime.date(2022, 10, 31)
assert invoice1.date_debit is None
assert invoice1.regie == regie
assert invoice1.payer_external_id == 'payer:1'
assert invoice1.payer_first_name == 'First1'
@ -1827,7 +1871,10 @@ def test_generate_invoices_from_lines():
assert isinstance(invoice2, DraftInvoice)
assert invoice2.label == 'Invoice from 2022-09-01 to 2022-09-30'
assert invoice2.total_amount == 4
assert invoice2.date_publication == datetime.date(2022, 10, 1)
assert invoice2.date_payment_deadline == datetime.date(2022, 10, 31)
assert invoice2.date_issue == datetime.date(2022, 10, 31)
assert invoice2.date_debit == datetime.date(2022, 11, 15)
assert invoice2.regie == regie
assert invoice2.payer_external_id == 'payer:2'
assert invoice2.payer_first_name == 'First2'
@ -1852,7 +1899,10 @@ def test_generate_invoices(mock_generate, mock_lines, mock_users, mock_agendas,
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),
)
mock_agendas.return_value = [agenda1, agenda2]
@ -1907,7 +1957,10 @@ def test_generate_invoices_errors(mock_generate, mock_lines, mock_users, mock_ag
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),
)
mock_lock.side_effect = ChronoError('foo baz')
@ -1927,94 +1980,6 @@ def test_generate_invoices_errors(mock_generate, mock_lines, mock_users, mock_ag
assert pool.exception == 'foo bar'
def test_generate_invoices_cmd():
regie = Regie.objects.create(label='Regie')
with mock.patch.object(Campaign, 'generate', autospec=True) as mock_generate:
with pytest.raises(CommandError) as excinfo:
call_command('generate_invoices')
assert (
'%s' % excinfo.value
== 'Error: the following arguments are required: date_start, date_end, regie_id'
)
assert mock_generate.call_args_list == []
with pytest.raises(CommandError) as excinfo:
call_command('generate_invoices', 'bad-value', '2022-10-01', regie.pk)
assert '%s' % excinfo.value == 'Bad value "bad-value" for date_start'
assert mock_generate.call_args_list == []
with pytest.raises(CommandError) as excinfo:
call_command('generate_invoices', '2022-09-01', 'bad-value', regie.pk)
assert '%s' % excinfo.value == 'Bad value "bad-value" for date_end'
assert mock_generate.call_args_list == []
with pytest.raises(CommandError) as excinfo:
call_command('generate_invoices', '2022-09-01', '2022-10-01', regie.pk, '--date-issue=bad-value')
assert '%s' % excinfo.value == 'Bad value "bad-value" for date_issue'
assert mock_generate.call_args_list == []
with pytest.raises(CommandError) as excinfo:
call_command('generate_invoices', '2022-09-01', '2022-10-01', 0)
assert '%s' % excinfo.value == 'Bad value "0" for regie_id'
assert mock_generate.call_args_list == []
assert Campaign.objects.count() == 0
call_command('generate_invoices', '2022-09-01', '2022-10-01', regie.pk)
assert Campaign.objects.count() == 1
campaign = Campaign.objects.latest('pk')
assert campaign.regie == regie
assert campaign.date_start == datetime.date(2022, 9, 1)
assert campaign.date_end == datetime.date(2022, 10, 1)
assert campaign.date_issue == campaign.date_end
assert mock_generate.call_args_list == [mock.call(campaign, spool=False)]
mock_generate.reset_mock()
# again
call_command('generate_invoices', '2022-09-01', '2022-10-01', regie.pk)
assert Campaign.objects.count() == 1
assert mock_generate.call_args_list == [mock.call(campaign, spool=False)]
mock_generate.reset_mock()
# with overlapping
with pytest.raises(CommandError) as excinfo:
call_command('generate_invoices', '2022-08-31', '2022-09-02', regie.pk)
assert '%s' % excinfo.value == 'Overlapping campaigns already exist'
assert mock_generate.call_args_list == []
with pytest.raises(CommandError) as excinfo:
call_command('generate_invoices', '2022-09-30', '2022-10-02', regie.pk)
assert '%s' % excinfo.value == 'Overlapping campaigns already exist'
assert mock_generate.call_args_list == []
# no overlapping
call_command('generate_invoices', '2022-08-01', '2022-09-01', regie.pk, '--date-issue=2022-10-31')
assert Campaign.objects.count() == 2
campaign = Campaign.objects.latest('pk')
assert mock_generate.call_args_list == [mock.call(campaign, spool=False)]
assert campaign.regie == regie
assert campaign.date_start == datetime.date(2022, 8, 1)
assert campaign.date_end == datetime.date(2022, 9, 1)
assert campaign.date_issue == datetime.date(2022, 10, 31)
mock_generate.reset_mock()
call_command('generate_invoices', '2022-10-01', '2022-11-01', regie.pk)
assert Campaign.objects.count() == 3
campaign = Campaign.objects.latest('pk')
assert mock_generate.call_args_list == [mock.call(campaign, spool=False)]
assert campaign.regie == regie
assert campaign.date_start == datetime.date(2022, 10, 1)
assert campaign.date_end == datetime.date(2022, 11, 1)
assert campaign.date_issue == campaign.date_end
regie2 = Regie.objects.create(label='Regie2')
mock_generate.reset_mock()
call_command('generate_invoices', '2022-08-31', '2022-09-02', regie2.pk)
assert Campaign.objects.count() == 4
campaign = Campaign.objects.latest('pk')
assert mock_generate.call_args_list == [mock.call(campaign, spool=False)]
assert campaign.regie == regie2
assert campaign.date_start == datetime.date(2022, 8, 31)
assert campaign.date_end == datetime.date(2022, 9, 2)
assert campaign.date_issue == campaign.date_end
def test_promote_pool():
today = datetime.date.today()
regie = Regie.objects.create(label='Regie')
@ -2022,7 +1987,10 @@ def test_promote_pool():
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),
)
old_pool = Pool.objects.create(
campaign=campaign,
@ -2038,7 +2006,10 @@ def test_promote_pool():
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),
)
other_pool = Pool.objects.create(
campaign=other_campaign,
@ -2046,7 +2017,9 @@ def test_promote_pool():
)
invoice1 = DraftInvoice.objects.create(
date_issue=datetime.date.today(),
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
payer_external_id='payer:1',
@ -2112,7 +2085,10 @@ def test_promote_pool():
pool=pool,
)
invoice2 = DraftInvoice.objects.create(
date_issue=datetime.date.today(),
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
date_debit=campaign.date_debit,
regie=regie,
pool=pool,
payer_external_id='payer:2',
@ -2213,7 +2189,9 @@ def test_promote_pool():
)
invoice3 = DraftInvoice.objects.create(
date_issue=datetime.date.today(),
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
payer_external_id='payer:1',
@ -2224,7 +2202,12 @@ def test_promote_pool():
)
old_invoice = DraftInvoice.objects.create(
date_issue=datetime.date.today(), regie=regie, pool=old_pool, payer_external_id='payer:1'
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=old_pool,
payer_external_id='payer:1',
)
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
@ -2270,7 +2253,12 @@ def test_promote_pool():
)
other_invoice = DraftInvoice.objects.create(
date_issue=datetime.date.today(), regie=regie, pool=other_pool, payer_external_id='payer:1'
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=other_pool,
payer_external_id='payer:1',
)
DraftInvoiceLine.objects.create(
event_date=datetime.date(2022, 9, 1),
@ -2350,7 +2338,10 @@ def test_promote_pool():
assert final_pool.exception == ''
final_invoice1 = Invoice.objects.order_by('pk')[0]
assert final_invoice1.date_publication == invoice1.date_publication
assert final_invoice1.date_payment_deadline == invoice1.date_payment_deadline
assert final_invoice1.date_issue == invoice1.date_issue
assert final_invoice1.date_debit == invoice1.date_debit
assert final_invoice1.regie == regie
assert final_invoice1.pool == final_pool
assert final_invoice1.payer_external_id == invoice1.payer_external_id
@ -2407,7 +2398,10 @@ def test_promote_pool():
assert final_line12.from_injected_line == injected_line12
final_invoice2 = Invoice.objects.order_by('pk')[1]
assert final_invoice2.date_publication == invoice2.date_publication
assert final_invoice2.date_payment_deadline == invoice2.date_payment_deadline
assert final_invoice2.date_issue == invoice2.date_issue
assert final_invoice2.date_debit == invoice2.date_debit
assert final_invoice2.regie == regie
assert final_invoice2.pool == final_pool
assert final_invoice2.payer_external_id == invoice2.payer_external_id
@ -2506,7 +2500,10 @@ def test_promote_pool():
assert final_orphan_line2.from_injected_line is None
final_invoice3 = Invoice.objects.order_by('pk')[2]
assert final_invoice3.date_publication == invoice3.date_publication
assert final_invoice3.date_payment_deadline == invoice3.date_payment_deadline
assert final_invoice3.date_issue == invoice3.date_issue
assert final_invoice3.date_debit == invoice3.date_debit
assert final_invoice3.regie == regie
assert final_invoice3.pool == final_pool
assert final_invoice3.payer_external_id == invoice3.payer_external_id

View File

@ -26,16 +26,31 @@ def test_invoice_total_amount(draft):
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=draft,
)
invoice = invoice_model.objects.create(date_issue=datetime.date.today(), regie=regie, pool=pool)
invoice = invoice_model.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
)
assert invoice.total_amount == 0
invoice2 = invoice_model.objects.create(date_issue=datetime.date.today(), regie=regie, pool=pool)
invoice2 = invoice_model.objects.create(
date_publication=campaign.date_publication,
date_payment_deadline=campaign.date_payment_deadline,
date_issue=campaign.date_issue,
regie=regie,
pool=pool,
)
assert invoice2.total_amount == 0
# line with error status, ignored