Facturation: ranger les campagnes de facturation dans une régie (#74516) #29
|
@ -19,7 +19,7 @@ import django_filters
|
|||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from lingo.invoicing.models import Campaign, DraftInvoice, DraftInvoiceLine, Invoice, InvoiceLine, Regie
|
||||
from lingo.invoicing.models import Campaign, DraftInvoice, DraftInvoiceLine, Invoice, InvoiceLine
|
||||
|
||||
|
||||
class CampaignForm(forms.ModelForm):
|
||||
|
@ -35,7 +35,7 @@ class CampaignForm(forms.ModelForm):
|
|||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
if 'date_start' in cleaned_data and 'date_end' in cleaned_data:
|
||||
overlapping_qs = Campaign.objects.extra(
|
||||
overlapping_qs = Campaign.objects.filter(regie=self.instance.regie).extra(
|
||||
where=["(date_start, date_end) OVERLAPS (%s, %s)"],
|
||||
params=[cleaned_data['date_start'], cleaned_data['date_end']],
|
||||
)
|
||||
|
@ -47,15 +47,7 @@ class CampaignForm(forms.ModelForm):
|
|||
return cleaned_data
|
||||
|
||||
|
||||
def regie_queryset(request):
|
||||
return Regie.objects.all()
|
||||
|
||||
|
||||
class AbstractInvoiceFilterSet(django_filters.FilterSet):
|
||||
regie = django_filters.ModelChoiceFilter(
|
||||
label=_('Regie'),
|
||||
queryset=regie_queryset,
|
||||
)
|
||||
# for Invoice
|
||||
number = django_filters.CharFilter(
|
||||
label=_('Invoice number'),
|
||||
|
@ -107,11 +99,6 @@ class InvoiceFilterSet(AbstractInvoiceFilterSet):
|
|||
|
||||
|
||||
class AbstractLineFilterSet(django_filters.FilterSet):
|
||||
regie = django_filters.ModelChoiceFilter(
|
||||
label=_('Regie'),
|
||||
queryset=regie_queryset,
|
||||
field_name='invoice__regie',
|
||||
)
|
||||
# for InvoiceLine
|
||||
invoice_number = django_filters.CharFilter(
|
||||
label=_('Invoice number'),
|
||||
|
|
|
@ -18,7 +18,7 @@ import datetime
|
|||
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from lingo.invoicing.models import Campaign
|
||||
from lingo.invoicing.models import Campaign, Regie
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
|
@ -27,6 +27,7 @@ class Command(BaseCommand):
|
|||
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):
|
||||
|
@ -38,6 +39,10 @@ class Command(BaseCommand):
|
|||
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()
|
||||
|
@ -47,15 +52,15 @@ class Command(BaseCommand):
|
|||
date_issue = date_end
|
||||
|
||||
try:
|
||||
campaign = Campaign.objects.get(date_start=date_start, date_end=date_end)
|
||||
campaign = Campaign.objects.get(date_start=date_start, date_end=date_end, regie=regie)
|
||||
except Campaign.DoesNotExist:
|
||||
campaigns = Campaign.objects.extra(
|
||||
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(
|
||||
date_start=date_start, date_end=date_end, date_issue=date_issue
|
||||
regie=regie, date_start=date_start, date_end=date_end, date_issue=date_issue
|
||||
)
|
||||
campaign.generate(spool=False)
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
from django.db import migrations
|
||||
lguerin marked this conversation as resolved
|
||||
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
Campaign = apps.get_model('invoicing', 'Campaign')
|
||||
Pool = apps.get_model('invoicing', 'Pool')
|
||||
DraftInvoice = apps.get_model('invoicing', 'DraftInvoice')
|
||||
DraftInvoiceLine = apps.get_model('invoicing', 'DraftInvoiceLine')
|
||||
Invoice = apps.get_model('invoicing', 'Invoice')
|
||||
InvoiceLine = apps.get_model('invoicing', 'InvoiceLine')
|
||||
|
||||
InvoiceLine.objects.all().delete()
|
||||
Invoice.objects.all().delete()
|
||||
DraftInvoiceLine.objects.all().delete()
|
||||
DraftInvoice.objects.all().delete()
|
||||
Pool.objects.all().delete()
|
||||
Campaign.objects.all().delete()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('invoicing', '0015_injected_lines'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward, reverse_code=migrations.RunPython.noop),
|
||||
]
|
|
@ -0,0 +1,17 @@
|
|||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('invoicing', '0016_campaign_regie'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='campaign',
|
||||
name='regie',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='invoicing.Regie'),
|
||||
pmarillonnet
commented
Ok, mais il faut alors dans la RegieDeleteView attraper les erreurs ( Ok, mais il faut alors dans la RegieDeleteView attraper les erreurs (`django.db.ProtectedError`) levées à la tentative de suppression alors qu’il existe encore des Campaign liées. Je ne vois ça nulle part (et la DeleteView django de base héritée ne gère pas cela du tout), je loupe un truc ?
Si c’est effectivement un oubli, sans doute qu’un petit test en plus serait le bienvenu.
lguerin
commented
Justement j'ai choisi de mettre PROTECT pour garantir que rien n'est supprimé si ce n'est pas explicitement géré par le code. Les données de facturation étant sensibles, je préfère lever une erreur et ne pas laisser passer un delete irréfléchi. Justement j'ai choisi de mettre PROTECT pour garantir que rien n'est supprimé si ce n'est pas explicitement géré par le code.
Un delete sauvage d'une régie n'est pas possible, l'orm vérifie les relations et balance une erreur avant de tenter la suppression
(l'orm ne délègue pas la gestion des FK et des relations à la DB, il le gère lui-même et se comporte en fonction du on_delete).
Les données de facturation étant sensibles, je préfère lever une erreur et ne pas laisser passer un delete irréfléchi.
(et une campagne n'a pas vocation à être supprimée, on doit conserver les données de facturation)
pmarillonnet
commented
Ok, à dérouler le code de Lingo puis de la DeleteView de base Django, j’étais dans l’impression que la RegieDeleteView sur une régie qui est encore liée à des campagnes allait lancer une bête trace python au lieu d’une erreur applicative propre. Je loupe un truc ? Ok, à dérouler le code de Lingo puis de la DeleteView de base Django, j’étais dans l’impression que la RegieDeleteView sur une régie qui est encore liée à des campagnes allait lancer une bête trace python au lieu d’une erreur applicative propre. Je loupe un truc ?
lguerin
commented
ha zut il y a une vue de suppression de régie ? bien vu :) ha zut il y a une vue de suppression de régie ? bien vu :)
je m'en vais donc interdire la suppression de régie si campagne ou facture liées.
lguerin
commented
commit ajouté commit ajouté
pmarillonnet
commented
¡Maravilloso! ¡Maravilloso!
|
||||
),
|
||||
]
|
|
@ -35,11 +35,6 @@ class RegieImportError(Exception):
|
|||
pass
|
||||
|
||||
|
||||
class RegieNotConfigured(Exception):
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
|
||||
|
||||
class PoolPromotionError(Exception):
|
||||
def __init__(self, msg):
|
||||
self.msg = msg
|
||||
|
@ -131,6 +126,7 @@ class Regie(models.Model):
|
|||
|
||||
|
||||
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_issue = models.DateField(_('Issue date'))
|
||||
|
@ -202,8 +198,8 @@ class Pool(models.Model):
|
|||
# get invoice lines for all subscribed users, for each agenda in the corresponding period
|
||||
lines = utils.get_all_invoice_lines(agendas=agendas, users=users, pool=self)
|
||||
# and generate invoices
|
||||
utils.generate_invoices_from_lines(agendas=agendas, all_lines=lines, pool=self)
|
||||
except (RegieNotConfigured, ChronoError) as e:
|
||||
utils.generate_invoices_from_lines(all_lines=lines, pool=self)
|
||||
except ChronoError as e:
|
||||
self.status = 'failed'
|
||||
self.exception = e.msg
|
||||
except Exception:
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
{% extends "lingo/invoicing/manager_campaign_list.html" %}
|
||||
{% extends "lingo/invoicing/manager_regie_detail.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-detail' object.pk %}">{{ object }}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-detail' regie.pk object.pk %}">{{ object }}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{{ object }}</h2>
|
||||
{% if not has_running_pool and not has_real_pool %}
|
||||
<span class="actions">
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-delete' pk=object.pk %}" rel="popup">{% trans "Delete" %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-edit' pk=object.pk %}" rel="popup">{% trans "Edit" %}</a>
|
||||
<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 %}" rel="popup">{% trans "Edit" %}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
@ -38,7 +38,7 @@
|
|||
<ul class="objects-list single-links">
|
||||
{% for pool in pools %}
|
||||
<li>
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-detail' pk=object.pk pool_pk=pool.pk %}">
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-detail' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk %}">
|
||||
{% if pool.draft_success_count or pool.success_count %}<span class="tag tag-success">{{ pool.draft_success_count|default:pool.success_count }}</span>{% endif %}
|
||||
{% if pool.draft_warning_count or pool.warning_count %}<span class="tag tag-warning">{{ pool.draft_warning_count|default:pool.warning_count }}</span>{% endif %}
|
||||
{% if pool.draft_error_count or pool.error_count %}<span class="tag tag-error">{{ pool.draft_error_count|default:pool.error_count }}</span>{% endif %}
|
||||
|
@ -57,7 +57,7 @@
|
|||
</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' pk=object.pk %}">{% trans 'Start a pool' %}</a>
|
||||
<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>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
{% extends "lingo/invoicing/manager_campaign_list.html" %}
|
||||
{% extends "lingo/invoicing/manager_regie_detail.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
{% if form.instance.pk %}
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-detail' object.pk %}">{{ object }}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-edit' object.pk %}">{% trans "Edit" %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-detail' regie.pk object.pk %}">{{ object }}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-edit' regie.pk object.pk %}">{% trans "Edit" %}</a>
|
||||
{% else %}
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-add' %}">{% trans "New campaign" %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-add' regie.pk %}">{% trans "New campaign" %}</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -26,9 +26,9 @@
|
|||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Save" %}</button>
|
||||
{% if object.pk %}
|
||||
<a class="cancel" href="{% url 'lingo-manager-invoicing-campaign-detail' object.pk %}">{% trans 'Cancel' %}</a>
|
||||
<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-campaign-list' %}">{% trans 'Cancel' %}</a>
|
||||
<a class="cancel" href="{% url 'lingo-manager-invoicing-regie-detail' regie.pk %}">{% trans 'Cancel' %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
{% extends "lingo/invoicing/manager_home.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-list' %}">{% trans "Campaigns" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
<h2>{% trans "Campaigns" %}</h2>
|
||||
<span class="actions">
|
||||
<a href="{% url 'lingo-manager-invoicing-non-invoiced-line-list' %}">{% trans 'Non invoiced lines' %}</a>
|
||||
<a rel="popup" href="{% url 'lingo-manager-invoicing-campaign-add' %}">{% trans 'New campaign' %}</a>
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="pk-information">
|
||||
<p>{% trans "Manage here invoicing campaigns." %}</p>
|
||||
</div>
|
||||
{% if object_list %}
|
||||
<div>
|
||||
<h3>{% trans "Campaigns" %}</h3>
|
||||
<ul class="objects-list single-links">
|
||||
{% for object in object_list %}
|
||||
<li>
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-detail' pk=object.pk %}">
|
||||
{{ object }}
|
||||
<span class="extra-info"> [{% trans "issue date:" %} {{ object.date_issue|date:'d/m/Y' }}]</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="big-msg-info">
|
||||
{% blocktrans trimmed %}
|
||||
This site doesn't have any campaign yet. Click on the "New campaign" button in the top
|
||||
right of the page to add a first one.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -17,10 +17,6 @@
|
|||
{% trans "Regies" %}
|
||||
<p>{% trans "Invoicing regies." %}</p>
|
||||
</a>
|
||||
<a class="button button-paragraph" href="{% url 'lingo-manager-invoicing-campaign-list' %}">
|
||||
{% trans "Campaigns" %}
|
||||
<p>{% trans "Manage invoicing campaigns." %}</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{% url 'lingo-manager-invoicing-pool-journal' pk=object.pk pool_pk=pool.pk as journal_url %}
|
||||
{% url 'lingo-manager-invoicing-pool-journal' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk as journal_url %}
|
||||
{% for line in object_list %}
|
||||
<li class="line" data-invoice-id="{{ line.invoice_id }}">
|
||||
<a href="{{ journal_url }}?pk={{ line.pk }}">#{{ line.pk }}</a>
|
||||
|
|
|
@ -30,11 +30,11 @@
|
|||
{% if line.status == 'error' and not pool.draft %}
|
||||
<br />
|
||||
{% if line.error_status %}
|
||||
<a class="error-status" href="{% url 'lingo-manager-invoicing-line-set-error-status' pk=object.pk pool_pk=pool.pk line_pk=line.pk status='reset' %}">{% trans "reset" %}</a>
|
||||
<a class="error-status" href="{% url 'lingo-manager-invoicing-line-set-error-status' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk line_pk=line.pk status='reset' %}">{% trans "reset" %}</a>
|
||||
{% else %}
|
||||
<a class="error-status" href="{% url 'lingo-manager-invoicing-line-set-error-status' pk=object.pk pool_pk=pool.pk line_pk=line.pk status='ignore' %}">{% trans "ignore" %}</a>
|
||||
<a class="error-status" href="{% url 'lingo-manager-invoicing-line-set-error-status' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk line_pk=line.pk status='ignore' %}">{% trans "ignore" %}</a>
|
||||
-
|
||||
<a class="error-status" href="{% url 'lingo-manager-invoicing-line-set-error-status' pk=object.pk pool_pk=pool.pk line_pk=line.pk status='fix' %}">{% trans "mark as fixed" %}</a>
|
||||
<a class="error-status" href="{% url 'lingo-manager-invoicing-line-set-error-status' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk line_pk=line.pk status='fix' %}">{% trans "mark as fixed" %}</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{% extends "lingo/invoicing/manager_campaign_list.html" %}
|
||||
{% extends "lingo/invoicing/manager_regie_detail.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'lingo-manager-invoicing-non-invoiced-line-list' %}">{% trans "Non invoiced lines" %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-non-invoiced-line-list' regie_pk=regie.pk %}">{% trans "Non invoiced lines" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
|
@ -32,7 +32,7 @@
|
|||
{{ line.event_date|date:"d/m/Y" }} - {{ line.label }}
|
||||
<br />
|
||||
{% if line.status == 'error'%}
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-journal' pk=line.campaign_id pool_pk=line.pool_id %}?pk={{ line.pk }}">({{ line.slug }})</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-journal' regie_pk=regie.pk pk=line.campaign_id pool_pk=line.pool_id %}?pk={{ line.pk }}">({{ line.slug }})</a>
|
||||
{% else %}
|
||||
({{ line.slug }})
|
||||
{% endif %}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'lingo-manager-invoicing-campaign-add' %}">{% trans "Start a pool" %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-add' regie.pk object.pk %}">{% trans "Start a pool" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
|
@ -16,7 +16,7 @@
|
|||
<p>{% trans "Are you sure you want to start a new pool?" %}</p>
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Run" %}</button>
|
||||
<a class="cancel" href="{% url 'lingo-manager-invoicing-campaign-detail' object.pk %}">{% trans 'Cancel' %}</a>
|
||||
<a class="cancel" href="{% url 'lingo-manager-invoicing-campaign-detail' regie.pk object.pk %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-detail' pk=object.pk pool_pk=pool.pk %}">{% trans "Pool" %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-detail' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk %}">{% trans "Pool" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
|
@ -14,12 +14,12 @@
|
|||
{{ pool.created_at|date:"DATETIME_FORMAT" }}
|
||||
</h2>
|
||||
<span class="actions">
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-journal' pk=object.pk pool_pk=pool.pk %}">{% trans "Journal" %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-journal' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk %}">{% trans "Journal" %}</a>
|
||||
{% if pool.draft and pool.status != 'registered' and pool.status != 'running' %}
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-delete' pk=object.pk pool_pk=pool.pk %}" rel="popup">{% trans "Delete" %}</a>
|
||||
<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 pool.draft and pool.status == 'completed' and pool.is_last %}
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-promote' pk=object.pk pool_pk=pool.pk %}" rel="popup">{% trans "Promote" %}</a>
|
||||
<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 %}
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
@ -45,15 +45,15 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% url 'lingo-manager-invoicing-pool-journal' pk=object.pk pool_pk=pool.pk as journal_url %}
|
||||
{% url 'lingo-manager-invoicing-pool-journal' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk as journal_url %}
|
||||
<div>
|
||||
<ul class="objects-list">
|
||||
{% for invoice in object_list %}
|
||||
<li class="invoice untoggled" data-invoice-id="{{ invoice.pk }}" data-invoice-lines-url="{% url 'lingo-manager-invoicing-invoice-line-list' pk=object.pk pool_pk=pool.pk invoice_pk=invoice.pk %}">
|
||||
<li class="invoice untoggled" data-invoice-id="{{ invoice.pk }}" data-invoice-lines-url="{% url 'lingo-manager-invoicing-invoice-line-list' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk invoice_pk=invoice.pk %}">
|
||||
{% if pool.draft %}
|
||||
{% blocktrans with number=invoice.pk payer=invoice.payer amount=invoice.total_amount %}Invoice <a href="{{ journal_url }}?invoice_id={{ number }}">PROFORMA-{{ number }}</a> addressed to <a href="{{ journal_url }}?payer_external_id={{ payer }}">{{ payer }}</a>, amount {{ amount }}€{% endblocktrans %}
|
||||
{% else %}
|
||||
{% blocktrans with invoice_number=invoice.formatted_number payer=invoice.payer amount=invoice.total_amount number=invoice.number regie_id=invoice.regie_id %}Invoice <a href="{{ journal_url }}?invoice_number={{ number }}®ie={{ regie_id }}">{{ invoice_number }}</a> addressed to <a href="{{ journal_url }}?payer_external_id={{ payer }}">{{ payer }}</a>, amount {{ amount }}€{% endblocktrans %}
|
||||
{% blocktrans with invoice_number=invoice.formatted_number payer=invoice.payer amount=invoice.total_amount number=invoice.number %}Invoice <a href="{{ journal_url }}?invoice_number={{ number }}">{{ invoice_number }}</a> addressed to <a href="{{ journal_url }}?payer_external_id={{ payer }}">{{ payer }}</a>, amount {{ amount }}€{% endblocktrans %}
|
||||
{% endif %}
|
||||
<span class="togglable"></span>
|
||||
</li>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-journal' pk=object.pk pool_pk=pool.pk %}">{% trans "Journal" %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-journal' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk %}">{% trans "Journal" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
|
@ -15,7 +15,7 @@
|
|||
</h2>
|
||||
{% if pool.draft and pool.status != 'registered' and pool.status != 'running' %}
|
||||
<span class="actions">
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-delete' pk=object.pk pool_pk=pool.pk %}" rel="popup">{% trans "Delete" %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-delete' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk %}" rel="popup">{% trans "Delete" %}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-promote' pk=object.pk pool_pk=pool.pk %}">{% trans "Promote" %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-pool-promote' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk %}">{% trans "Promote" %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
|
@ -16,7 +16,7 @@
|
|||
<p>{% trans "Are you sure you want to promote this pool ? This action is irreversible." %}</p>
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Promote" %}</button>
|
||||
<a class="cancel" href="{% url 'lingo-manager-invoicing-pool-detail' pk=object.pk pool_pk=pool.pk %}">{% trans 'Cancel' %}</a>
|
||||
<a class="cancel" href="{% url 'lingo-manager-invoicing-pool-detail' regie_pk=regie.pk pk=object.pk pool_pk=pool.pk %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
|
@ -3,14 +3,17 @@
|
|||
|
||||
{% block breadcrumb %}
|
||||
{{ block.super }}
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-detail' regie.pk %}">{{ object }}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-detail' regie.pk %}">{{ regie }}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block appbar %}
|
||||
{{ block.super }}
|
||||
<span class="actions">
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-delete' pk=regie.pk %}" rel="popup">{% trans "Delete" %}</a>
|
||||
{% if not has_related_objects %}
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-delete' pk=regie.pk %}" rel="popup">{% trans "Delete" %}</a>
|
||||
{% endif %}
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-edit' pk=regie.pk %}" rel="popup">{% trans "Edit" %}</a>
|
||||
<a href="{% url 'lingo-manager-invoicing-non-invoiced-line-list' regie_pk=regie.pk %}">{% trans 'Non invoiced lines' %}</a>
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -20,6 +23,7 @@
|
|||
<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-usage" aria-selected="false" id="tab-usage" role="tab" tabindex="-1">{% trans "Used in agendas" %}</button>
|
||||
<button aria-controls="panel-campaigns" aria-selected="false" id="tab-campaigns" role="tab" tabindex="-1">{% trans "Campaigns" %}</button>
|
||||
</div>
|
||||
<div class="pk-tabs--container">
|
||||
|
||||
|
@ -57,6 +61,22 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-campaigns" hidden="" id="panel-campaigns" role="tabpanel" tabindex="0">
|
||||
lguerin marked this conversation as resolved
pmarillonnet
commented
Dans le gabarit initial que ce bout de gabarit remplace, il y avait un message lorsque cette liste d’objets était vide (“This site doesn't have any campaign yet. […]“). Est-ce volontaire de l’avoir laissé de coté dans cette nouvelle version ? Dans le gabarit initial que ce bout de gabarit remplace, il y avait un message lorsque cette liste d’objets était vide (“This site doesn't have any campaign yet. […]“). Est-ce volontaire de l’avoir laissé de coté dans cette nouvelle version ?
lguerin
commented
Dans le template précédent, on avait une liste de campagnes et c'est tout. Sur la page de détail d'une campagne, dans l'onglet pool il n'y a pas on plus de message lorsque par de pools. Si tu insistes je peux ajouter ça pour les campagnes et pour les pools (pour que ce soit homogène) Dans le template précédent, on avait une liste de campagnes et c'est tout.
Là on est dans un onglet sur la page de détail d'une régie.
Sur la page de détail d'une campagne, dans l'onglet pool il n'y a pas on plus de message lorsque par de pools.
Si tu insistes je peux ajouter ça pour les campagnes et pour les pools (pour que ce soit homogène)
pmarillonnet
commented
Non, je ne connais pas assez le métier pour insister, je signalais juste ce qui me semblait être une incohérence de forme, mais il s’avère que c’est délibéré. Ok pour moi. Non, je ne connais pas assez le métier pour insister, je signalais juste ce qui me semblait être une incohérence de forme, mais il s’avère que c’est délibéré. Ok pour moi.
|
||||
<ul class="objects-list single-links">
|
||||
{% for campaign in campaigns %}
|
||||
<li>
|
||||
<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>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<div class="panel--buttons">
|
||||
<a rel="popup" class="pk-button" href="{% url 'lingo-manager-invoicing-campaign-add' regie_pk=regie.pk %}">{% trans "New campaign" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -43,64 +43,63 @@ urlpatterns = [
|
|||
),
|
||||
path('regies/import/', views.regies_import, name='lingo-manager-invoicing-regie-import'),
|
||||
path('regies/export/', views.regies_export, name='lingo-manager-invoicing-regie-export'),
|
||||
path('campaigns/', views.campaign_list, name='lingo-manager-invoicing-campaign-list'),
|
||||
path(
|
||||
'campaign/add/',
|
||||
'regie/<int:regie_pk>/campaign/add/',
|
||||
views.campaign_add,
|
||||
name='lingo-manager-invoicing-campaign-add',
|
||||
),
|
||||
path(
|
||||
'campaign/<int:pk>/',
|
||||
'regie/<int:regie_pk>/campaign/<int:pk>/',
|
||||
views.campaign_detail,
|
||||
name='lingo-manager-invoicing-campaign-detail',
|
||||
),
|
||||
path(
|
||||
'campaign/<int:pk>/edit/',
|
||||
'regie/<int:regie_pk>/campaign/<int:pk>/edit/',
|
||||
views.campaign_edit,
|
||||
name='lingo-manager-invoicing-campaign-edit',
|
||||
),
|
||||
path(
|
||||
'campaign/<int:pk>/delete/',
|
||||
'regie/<int:regie_pk>/campaign/<int:pk>/delete/',
|
||||
views.campaign_delete,
|
||||
name='lingo-manager-invoicing-campaign-delete',
|
||||
),
|
||||
path(
|
||||
'campaign/<int:pk>/pool/add/',
|
||||
'regie/<int:regie_pk>/campaign/<int:pk>/pool/add/',
|
||||
views.pool_add,
|
||||
name='lingo-manager-invoicing-pool-add',
|
||||
),
|
||||
path(
|
||||
'campaign/<int:pk>/pool/<int:pool_pk>/',
|
||||
'regie/<int:regie_pk>/campaign/<int:pk>/pool/<int:pool_pk>/',
|
||||
views.pool_detail,
|
||||
name='lingo-manager-invoicing-pool-detail',
|
||||
),
|
||||
path(
|
||||
'campaign/<int:pk>/pool/<int:pool_pk>/journal/',
|
||||
'regie/<int:regie_pk>/campaign/<int:pk>/pool/<int:pool_pk>/journal/',
|
||||
views.pool_journal,
|
||||
name='lingo-manager-invoicing-pool-journal',
|
||||
),
|
||||
path(
|
||||
'campaign/<int:pk>/pool/<int:pool_pk>/promote/',
|
||||
'regie/<int:regie_pk>/campaign/<int:pk>/pool/<int:pool_pk>/promote/',
|
||||
views.pool_promote,
|
||||
name='lingo-manager-invoicing-pool-promote',
|
||||
),
|
||||
path(
|
||||
'campaign/<int:pk>/pool/<int:pool_pk>/delete/',
|
||||
'regie/<int:regie_pk>/campaign/<int:pk>/pool/<int:pool_pk>/delete/',
|
||||
views.pool_delete,
|
||||
name='lingo-manager-invoicing-pool-delete',
|
||||
),
|
||||
path(
|
||||
'ajax/campaign/<int:pk>/pool/<int:pool_pk>/invoice/<int:invoice_pk>/lines/',
|
||||
'ajax/regie/<int:regie_pk>/campaign/<int:pk>/pool/<int:pool_pk>/invoice/<int:invoice_pk>/lines/',
|
||||
views.invoice_line_list,
|
||||
name='lingo-manager-invoicing-invoice-line-list',
|
||||
),
|
||||
path(
|
||||
'ajax/campaign/<int:pk>/pool/<int:pool_pk>/line/<int:line_pk>/<slug:status>/',
|
||||
'ajax/regie/<int:regie_pk>/campaign/<int:pk>/pool/<int:pool_pk>/line/<int:line_pk>/<slug:status>/',
|
||||
views.line_set_error_status,
|
||||
name='lingo-manager-invoicing-line-set-error-status',
|
||||
),
|
||||
path(
|
||||
'campaigns/non-invoiced-lines/',
|
||||
'regie/<int:regie_pk>/non-invoiced-lines/',
|
||||
views.non_invoiced_line_list,
|
||||
name='lingo-manager-invoicing-non-invoiced-line-list',
|
||||
),
|
||||
|
|
|
@ -22,12 +22,14 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
from lingo.agendas.chrono import get_check_status, get_subscriptions
|
||||
from lingo.agendas.models import Agenda
|
||||
from lingo.invoicing.models import DraftInvoice, DraftInvoiceLine, InjectedLine, RegieNotConfigured
|
||||
from lingo.invoicing.models import DraftInvoice, DraftInvoiceLine, InjectedLine
|
||||
from lingo.pricing.models import AgendaPricing, AgendaPricingNotFound, PricingError
|
||||
|
||||
|
||||
def get_agendas(pool):
|
||||
agendas_pricings = AgendaPricing.objects.filter(flat_fee_schedule=False).extra(
|
||||
agendas_pricings = AgendaPricing.objects.filter(
|
||||
flat_fee_schedule=False, agendas__regie=pool.campaign.regie
|
||||
).extra(
|
||||
where=["(date_start, date_end) OVERLAPS (%s, %s)"],
|
||||
params=[pool.campaign.date_start, pool.campaign.date_end],
|
||||
)
|
||||
|
@ -147,6 +149,7 @@ def get_invoice_lines_for_user(agendas, agendas_pricings, user_external_id, user
|
|||
# fetch injected lines
|
||||
injected_lines = (
|
||||
InjectedLine.objects.filter(
|
||||
regie=pool.campaign.regie,
|
||||
event_date__lt=pool.campaign.date_end,
|
||||
user_external_id=user_external_id,
|
||||
)
|
||||
|
@ -213,48 +216,34 @@ def get_all_invoice_lines(agendas, users, pool):
|
|||
return lines
|
||||
|
||||
|
||||
def generate_invoices_from_lines(agendas, all_lines, pool):
|
||||
agendas_by_slug = {a.slug: a for a in agendas}
|
||||
def generate_invoices_from_lines(all_lines, pool):
|
||||
regie = pool.campaign.regie
|
||||
|
||||
# regroup lines by regie, and by payer_external_id (payer)
|
||||
lines_by_regie = {}
|
||||
# regroup lines by payer_external_id (payer)
|
||||
lines = {}
|
||||
for line in all_lines:
|
||||
if line.status != 'success':
|
||||
# ignore lines in error
|
||||
continue
|
||||
if line.from_injected_line:
|
||||
regie = line.from_injected_line.regie
|
||||
else:
|
||||
agenda_slug = line.event['agenda']
|
||||
if agenda_slug not in agendas_by_slug:
|
||||
# should not happen
|
||||
continue
|
||||
regie = agendas_by_slug[agenda_slug].regie
|
||||
if not regie:
|
||||
raise RegieNotConfigured(_('Regie not configured on %s') % agenda_slug)
|
||||
if regie.pk not in lines_by_regie:
|
||||
lines_by_regie[regie.pk] = {}
|
||||
regie_subs = lines_by_regie[regie.pk]
|
||||
if line.payer_external_id not in regie_subs:
|
||||
regie_subs[line.payer_external_id] = []
|
||||
regie_subs[line.payer_external_id].append(line)
|
||||
if line.payer_external_id not in lines:
|
||||
lines[line.payer_external_id] = []
|
||||
lines[line.payer_external_id].append(line)
|
||||
|
||||
# generate invoices by regie and by payer_external_id (payer)
|
||||
invoices = []
|
||||
for regie_id, regie_subs in lines_by_regie.items():
|
||||
for payer_external_id, adult_lines in regie_subs.items():
|
||||
invoice = DraftInvoice.objects.create(
|
||||
label=_('Invoice from %(start)s to %(end)s')
|
||||
% {
|
||||
'start': pool.campaign.date_start,
|
||||
'end': pool.campaign.date_end - datetime.timedelta(days=1),
|
||||
},
|
||||
date_issue=pool.campaign.date_issue,
|
||||
regie_id=regie_id,
|
||||
payer=payer_external_id,
|
||||
pool=pool,
|
||||
)
|
||||
DraftInvoiceLine.objects.filter(pk__in=[line.pk for line in adult_lines]).update(invoice=invoice)
|
||||
invoices.append(invoice)
|
||||
for payer_external_id, adult_lines in lines.items():
|
||||
invoice = DraftInvoice.objects.create(
|
||||
label=_('Invoice from %(start)s to %(end)s')
|
||||
% {
|
||||
'start': pool.campaign.date_start,
|
||||
'end': pool.campaign.date_end - datetime.timedelta(days=1),
|
||||
},
|
||||
date_issue=pool.campaign.date_issue,
|
||||
regie=regie,
|
||||
payer=payer_external_id,
|
||||
pool=pool,
|
||||
)
|
||||
DraftInvoiceLine.objects.filter(pk__in=[line.pk for line in adult_lines]).update(invoice=invoice)
|
||||
invoices.append(invoice)
|
||||
|
||||
return invoices
|
||||
|
|
|
@ -48,6 +48,7 @@ from lingo.invoicing.forms import (
|
|||
)
|
||||
from lingo.invoicing.models import (
|
||||
Campaign,
|
||||
Counter,
|
||||
DraftInvoice,
|
||||
DraftInvoiceLine,
|
||||
InjectedLine,
|
||||
|
@ -111,6 +112,13 @@ class RegieDetailView(DetailView):
|
|||
def get_context_data(self, **kwargs):
|
||||
kwargs['regie'] = self.object
|
||||
kwargs['agendas'] = Agenda.objects.filter(regie=self.object)
|
||||
kwargs['campaigns'] = self.object.campaign_set.all().order_by('-date_start')
|
||||
has_related_objects = False
|
||||
if kwargs['campaigns']:
|
||||
has_related_objects = True
|
||||
elif self.object.injectedline_set.exists():
|
||||
has_related_objects = True
|
||||
kwargs['has_related_objects'] = has_related_objects
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
|
@ -133,6 +141,14 @@ class RegieDeleteView(DeleteView):
|
|||
template_name = 'lingo/manager_confirm_delete.html'
|
||||
model = Regie
|
||||
|
||||
def get_queryset(self):
|
||||
return super().get_queryset().filter(campaign__isnull=True, injectedline__isnull=True)
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
Counter.objects.filter(regie=self.object).delete()
|
||||
return super().delete(request, *args, **kwargs)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('lingo-manager-invoicing-regie-list')
|
||||
|
||||
|
@ -202,22 +218,26 @@ class RegiesImportView(FormView):
|
|||
regies_import = RegiesImportView.as_view()
|
||||
|
||||
|
||||
class CampaignListView(ListView):
|
||||
template_name = 'lingo/invoicing/manager_campaign_list.html'
|
||||
model = Campaign
|
||||
ordering = '-date_start'
|
||||
|
||||
|
||||
campaign_list = CampaignListView.as_view()
|
||||
|
||||
|
||||
class CampaignAddView(CreateView):
|
||||
template_name = 'lingo/invoicing/manager_campaign_form.html'
|
||||
model = Campaign
|
||||
form_class = CampaignForm
|
||||
|
||||
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_context_data(self, **kwargs):
|
||||
kwargs['regie'] = self.regie
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs['instance'] = Campaign(regie=self.regie)
|
||||
return kwargs
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('lingo-manager-invoicing-campaign-detail', args=[self.object.pk])
|
||||
return reverse('lingo-manager-invoicing-campaign-detail', args=[self.regie.pk, self.object.pk])
|
||||
|
||||
|
||||
campaign_add = CampaignAddView.as_view()
|
||||
|
@ -227,6 +247,13 @@ class CampaignDetailView(DetailView):
|
|||
template_name = 'lingo/invoicing/manager_campaign_detail.html'
|
||||
model = Campaign
|
||||
|
||||
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)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
draft_lines = DraftInvoiceLine.objects.filter(pool=OuterRef('pk')).order_by().values('pool')
|
||||
count_draft_error = draft_lines.filter(status='error').annotate(count=Count('pool')).values('count')
|
||||
|
@ -242,6 +269,7 @@ class CampaignDetailView(DetailView):
|
|||
)
|
||||
count_warning = lines.filter(status='warning').annotate(count=Count('pool')).values('count')
|
||||
count_success = lines.filter(status='success').annotate(count=Count('pool')).values('count')
|
||||
kwargs['regie'] = self.regie
|
||||
kwargs['pools'] = self.object.pool_set.annotate(
|
||||
draft_error_count=Coalesce(Subquery(count_draft_error, output_field=IntegerField()), Value(0)),
|
||||
draft_warning_count=Coalesce(
|
||||
|
@ -267,16 +295,25 @@ class CampaignEditView(UpdateView):
|
|||
model = Campaign
|
||||
form_class = CampaignForm
|
||||
|
||||
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__draft=False)
|
||||
.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 reverse('lingo-manager-invoicing-campaign-detail', args=[self.object.pk])
|
||||
return reverse('lingo-manager-invoicing-campaign-detail', args=[self.regie.pk, self.object.pk])
|
||||
|
||||
|
||||
campaign_edit = CampaignEditView.as_view()
|
||||
|
@ -286,10 +323,15 @@ class CampaignDeleteView(DeleteView):
|
|||
template_name = 'lingo/manager_confirm_delete.html'
|
||||
model = Campaign
|
||||
|
||||
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__draft=False)
|
||||
.exclude(pool__status__in=['registered', 'running'])
|
||||
)
|
||||
|
@ -302,7 +344,7 @@ class CampaignDeleteView(DeleteView):
|
|||
return super().delete(request, *args, **kwargs)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse('lingo-manager-invoicing-campaign-list')
|
||||
return '%s#open:campaigns' % reverse('lingo-manager-invoicing-regie-detail', args=[self.regie.pk])
|
||||
|
||||
|
||||
campaign_delete = CampaignDeleteView.as_view()
|
||||
|
@ -313,7 +355,8 @@ class PoolDetailView(ListView):
|
|||
paginate_by = 100
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.campaign = get_object_or_404(Campaign, pk=kwargs['pk'])
|
||||
self.regie = get_object_or_404(Regie, pk=kwargs['regie_pk'])
|
||||
self.campaign = get_object_or_404(Campaign, pk=kwargs['pk'], regie=self.regie)
|
||||
self.object = get_object_or_404(Pool, pk=kwargs['pool_pk'], campaign=self.campaign)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
@ -331,6 +374,7 @@ class PoolDetailView(ListView):
|
|||
return self.filterset.qs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['regie'] = self.regie
|
||||
kwargs['object'] = self.campaign
|
||||
kwargs['pool'] = self.object
|
||||
kwargs['filterset'] = self.filterset
|
||||
|
@ -356,7 +400,8 @@ class PoolJournalView(ListView):
|
|||
paginate_by = 100
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.campaign = get_object_or_404(Campaign, pk=kwargs['pk'])
|
||||
self.regie = get_object_or_404(Regie, pk=kwargs['regie_pk'])
|
||||
self.campaign = get_object_or_404(Campaign, pk=kwargs['pk'], regie=self.regie)
|
||||
self.object = get_object_or_404(Pool, pk=kwargs['pool_pk'], campaign=self.campaign)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
@ -377,6 +422,7 @@ class PoolJournalView(ListView):
|
|||
return self.filterset.qs if data and [v for v in data.values() if v] else all_lines
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['regie'] = self.regie
|
||||
kwargs['object'] = self.campaign
|
||||
kwargs['pool'] = self.object
|
||||
kwargs['filterset'] = self.filterset
|
||||
|
@ -390,21 +436,26 @@ class PoolAddView(FormView):
|
|||
template_name = 'lingo/invoicing/manager_pool_add.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.exclude(pool__draft=False).exclude(pool__status__in=['registered', 'running']),
|
||||
Campaign.objects.filter(regie=self.regie)
|
||||
.exclude(pool__draft=False)
|
||||
.exclude(pool__status__in=['registered', 'running']),
|
||||
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):
|
||||
self.object.generate()
|
||||
return redirect(
|
||||
'%s#open:pools' % reverse('lingo-manager-invoicing-campaign-detail', args=[self.object.pk])
|
||||
'%s#open:pools'
|
||||
% reverse('lingo-manager-invoicing-campaign-detail', args=[self.regie.pk, self.object.pk])
|
||||
)
|
||||
|
||||
|
||||
|
@ -415,9 +466,11 @@ class PoolPromoteView(FormView):
|
|||
template_name = 'lingo/invoicing/manager_pool_promote.html'
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.regie = get_object_or_404(Regie, pk=kwargs['regie_pk'])
|
||||
self.object = get_object_or_404(
|
||||
Pool,
|
||||
campaign__id=kwargs['pk'],
|
||||
campaign__regie=self.regie,
|
||||
pk=kwargs['pool_pk'],
|
||||
draft=True,
|
||||
status='completed',
|
||||
|
@ -428,6 +481,7 @@ class PoolPromoteView(FormView):
|
|||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['form'] = None
|
||||
kwargs['regie'] = self.regie
|
||||
kwargs['object'] = self.object.campaign
|
||||
kwargs['pool'] = self.object
|
||||
return super().get_context_data(**kwargs)
|
||||
|
@ -436,7 +490,9 @@ class PoolPromoteView(FormView):
|
|||
self.object.promote()
|
||||
return redirect(
|
||||
'%s#open:pools'
|
||||
% reverse('lingo-manager-invoicing-campaign-detail', args=[self.object.campaign.pk])
|
||||
% reverse(
|
||||
'lingo-manager-invoicing-campaign-detail', args=[self.regie.pk, self.object.campaign.pk]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
@ -449,8 +505,11 @@ class PoolDeleteView(DeleteView):
|
|||
pk_url_kwarg = 'pool_pk'
|
||||
|
||||
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.exclude(pool__draft=False).exclude(pool__status__in=['registered', 'running']),
|
||||
Campaign.objects.filter(regie=self.regie)
|
||||
.exclude(pool__draft=False)
|
||||
.exclude(pool__status__in=['registered', 'running']),
|
||||
pk=kwargs['pk'],
|
||||
)
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
@ -465,7 +524,9 @@ class PoolDeleteView(DeleteView):
|
|||
return super().delete(request, *args, **kwargs)
|
||||
|
||||
def get_success_url(self):
|
||||
return '%s#open:pools' % reverse('lingo-manager-invoicing-campaign-detail', args=[self.campaign.pk])
|
||||
return '%s#open:pools' % reverse(
|
||||
'lingo-manager-invoicing-campaign-detail', args=[self.regie.pk, self.campaign.pk]
|
||||
)
|
||||
|
||||
|
||||
pool_delete = PoolDeleteView.as_view()
|
||||
|
@ -475,7 +536,10 @@ class InvoiceLineListView(ListView):
|
|||
template_name = 'lingo/invoicing/manager_invoice_lines.html'
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.pool = get_object_or_404(Pool, pk=kwargs['pool_pk'], campaign_id=kwargs['pk'])
|
||||
self.regie = get_object_or_404(Regie, pk=kwargs['regie_pk'])
|
||||
self.pool = get_object_or_404(
|
||||
Pool, pk=kwargs['pool_pk'], campaign_id=kwargs['pk'], campaign__regie=self.regie
|
||||
)
|
||||
invoice_model = Invoice
|
||||
if self.pool.draft:
|
||||
invoice_model = DraftInvoice
|
||||
|
@ -486,6 +550,7 @@ class InvoiceLineListView(ListView):
|
|||
return self.invoice.lines.all().order_by('user_external_id', 'event_date', 'pk')
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['regie'] = self.pool.campaign.regie
|
||||
kwargs['object'] = self.pool.campaign
|
||||
kwargs['pool'] = self.pool
|
||||
return super().get_context_data(**kwargs)
|
||||
|
@ -499,14 +564,24 @@ class LineSetErrorStatusView(DetailView):
|
|||
pk_url_kwarg = 'line_pk'
|
||||
template_name = 'lingo/invoicing/manager_line_detail_fragment.html'
|
||||
|
||||
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(status='error', pool=self.kwargs['pool_pk'], pool__campaign=self.kwargs['pk'])
|
||||
.filter(
|
||||
status='error',
|
||||
pool=self.kwargs['pool_pk'],
|
||||
pool__campaign=self.kwargs['pk'],
|
||||
pool__campaign__regie=self.regie,
|
||||
)
|
||||
)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['regie'] = self.regie
|
||||
kwargs['object'] = self.object.pool.campaign
|
||||
kwargs['pool'] = self.object.pool
|
||||
kwargs['line'] = self.object
|
||||
|
@ -530,7 +605,9 @@ class LineSetErrorStatusView(DetailView):
|
|||
return self.render_to_response(context)
|
||||
|
||||
return redirect(
|
||||
reverse('lingo-manager-invoicing-pool-journal', args=[kwargs['pk'], kwargs['pool_pk']])
|
||||
reverse(
|
||||
'lingo-manager-invoicing-pool-journal', args=[self.regie.pk, kwargs['pk'], kwargs['pool_pk']]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
@ -541,6 +618,10 @@ class NonInvoicedLineListView(ListView):
|
|||
template_name = 'lingo/invoicing/manager_non_invoiced_line_list.html'
|
||||
paginate_by = 100
|
||||
|
||||
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):
|
||||
fields = [
|
||||
'pk',
|
||||
|
@ -558,9 +639,11 @@ class NonInvoicedLineListView(ListView):
|
|||
'status',
|
||||
'pool_id',
|
||||
]
|
||||
qs1 = InvoiceLine.objects.filter(status='error', error_status='').values(*fields)
|
||||
qs1 = InvoiceLine.objects.filter(
|
||||
status='error', error_status='', pool__campaign__regie=self.regie
|
||||
).values(*fields)
|
||||
qs2 = (
|
||||
InjectedLine.objects.filter(invoiceline__isnull=True)
|
||||
InjectedLine.objects.filter(invoiceline__isnull=True, regie=self.regie)
|
||||
.annotate(
|
||||
user_name=Value('', output_field=CharField()),
|
||||
event=Value({}, output_field=JSONField()),
|
||||
|
@ -574,6 +657,7 @@ class NonInvoicedLineListView(ListView):
|
|||
return qs
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
kwargs['regie'] = self.regie
|
||||
context = super().get_context_data(**kwargs)
|
||||
pools = Pool.objects.filter(draft=False).in_bulk()
|
||||
for line in context['object_list']:
|
||||
|
|
|
@ -22,7 +22,3 @@ def test_manager_invoicing_home(app, admin_user):
|
|||
'div#lingo-manager-main div a[href="%s"]' % reverse('lingo-manager-invoicing-regie-list')
|
||||
)
|
||||
assert anchor.text().startswith('Regies')
|
||||
anchor = resp.pyquery(
|
||||
'div#lingo-manager-main div a[href="%s"]' % reverse('lingo-manager-invoicing-campaign-list')
|
||||
)
|
||||
assert anchor.text().startswith('Campaigns')
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import datetime
|
||||
import json
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
@ -7,7 +8,7 @@ from django.urls import reverse
|
|||
from webtest import Upload
|
||||
|
||||
from lingo.agendas.models import Agenda
|
||||
from lingo.invoicing.models import Regie
|
||||
from lingo.invoicing.models import Campaign, Counter, InjectedLine, Regie
|
||||
from tests.utils import login
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
@ -138,6 +139,42 @@ def test_manager_invoicing_regie_delete(app, admin_user):
|
|||
assert Regie.objects.count() == 0
|
||||
assert urlparse(response.request.url).path == reverse('lingo-manager-invoicing-regie-list')
|
||||
|
||||
# can not delete regie containing campaign
|
||||
regie.save()
|
||||
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),
|
||||
)
|
||||
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
|
||||
resp = app.get(reverse('lingo-manager-invoicing-regie-delete', kwargs={'pk': regie.pk}), status=404)
|
||||
|
||||
campaign.delete()
|
||||
|
||||
# can not delete regie containing injected line
|
||||
injected_line = InjectedLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=1,
|
||||
unit_amount=1,
|
||||
total_amount=1,
|
||||
regie=regie,
|
||||
)
|
||||
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
|
||||
resp = app.get(reverse('lingo-manager-invoicing-regie-delete', kwargs={'pk': regie.pk}), status=404)
|
||||
|
||||
injected_line.delete()
|
||||
|
||||
# check counters are deleted
|
||||
Counter.get_count(regie=regie, name='bar')
|
||||
assert Counter.objects.count() == 1
|
||||
resp = app.get(reverse('lingo-manager-invoicing-regie-delete', kwargs={'pk': regie.pk}))
|
||||
response = resp.form.submit().follow()
|
||||
assert Regie.objects.count() == 0
|
||||
assert Counter.objects.count() == 0
|
||||
|
||||
|
||||
def test_manager_invoicing_regie_import_export(app, admin_user, freezer):
|
||||
freezer.move_to('2020-06-15')
|
||||
|
|
|
@ -22,7 +22,6 @@ from lingo.invoicing.models import (
|
|||
Pool,
|
||||
PoolPromotionError,
|
||||
Regie,
|
||||
RegieNotConfigured,
|
||||
)
|
||||
from lingo.pricing.models import AgendaPricing, Criteria, CriteriaCategory, Pricing, PricingError
|
||||
|
||||
|
@ -30,12 +29,16 @@ pytestmark = pytest.mark.django_db
|
|||
|
||||
|
||||
def test_get_agendas():
|
||||
agenda1 = Agenda.objects.create(label='Agenda 1')
|
||||
agenda2 = Agenda.objects.create(label='Agenda 2')
|
||||
agenda3 = Agenda.objects.create(label='Agenda 3')
|
||||
Agenda.objects.create(label='Agenda 4')
|
||||
regie1 = Regie.objects.create(label='Regie1')
|
||||
regie2 = Regie.objects.create(label='Regie2')
|
||||
agenda1 = Agenda.objects.create(label='Agenda 1', regie=regie1)
|
||||
agenda2 = Agenda.objects.create(label='Agenda 2', regie=regie1)
|
||||
agenda3 = Agenda.objects.create(label='Agenda 3', regie=regie1)
|
||||
Agenda.objects.create(label='Agenda 4', regie=regie1)
|
||||
agenda5 = Agenda.objects.create(label='Agenda 5', regie=regie2) # other regie
|
||||
pricing = Pricing.objects.create(label='Foo bar 1')
|
||||
campaign = Campaign.objects.create(
|
||||
regie=regie1,
|
||||
date_start=datetime.date(2022, 9, 1),
|
||||
date_end=datetime.date(2022, 10, 1),
|
||||
date_issue=datetime.date(2022, 10, 31),
|
||||
|
@ -72,7 +75,7 @@ def test_get_agendas():
|
|||
assert list(utils.get_agendas(pool=pool)) == []
|
||||
|
||||
# link agendas to agenda pricing
|
||||
agenda_pricing1.agendas.add(agenda1, agenda2)
|
||||
agenda_pricing1.agendas.add(agenda1, agenda2, agenda5)
|
||||
agenda_pricing2.agendas.add(agenda3)
|
||||
|
||||
assert list(utils.get_agendas(pool=pool)) == [agenda3]
|
||||
|
@ -104,8 +107,10 @@ def test_get_agendas():
|
|||
|
||||
@mock.patch('lingo.invoicing.utils.get_subscriptions')
|
||||
def test_get_users_from_subscriptions_error(mock_subscriptions):
|
||||
regie = Regie.objects.create(label='Regie')
|
||||
agenda = Agenda.objects.create(label='Agenda')
|
||||
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),
|
||||
|
@ -121,9 +126,11 @@ def test_get_users_from_subscriptions_error(mock_subscriptions):
|
|||
|
||||
@mock.patch('lingo.invoicing.utils.get_subscriptions')
|
||||
def test_get_users_from_subscriptions(mock_subscriptions):
|
||||
regie = Regie.objects.create(label='Regie')
|
||||
agenda1 = Agenda.objects.create(label='Agenda 1')
|
||||
agenda2 = Agenda.objects.create(label='Agenda 2')
|
||||
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),
|
||||
|
@ -201,8 +208,10 @@ def test_get_users_from_subscriptions(mock_subscriptions):
|
|||
|
||||
@mock.patch('lingo.invoicing.utils.get_check_status')
|
||||
def test_get_invoice_lines_for_user_check_status_error(mock_status):
|
||||
regie = Regie.objects.create(label='Regie')
|
||||
agenda = Agenda.objects.create(label='Agenda')
|
||||
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),
|
||||
|
@ -227,6 +236,7 @@ def test_get_invoice_lines_for_user_check_status_error(mock_status):
|
|||
@mock.patch('lingo.pricing.models.AgendaPricing.get_pricing_data_for_event')
|
||||
def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_status, injected_lines):
|
||||
regie = Regie.objects.create(label='Regie')
|
||||
other_regie = Regie.objects.create(label='Other Regie')
|
||||
agenda1 = Agenda.objects.create(label='Agenda 1')
|
||||
agenda2 = Agenda.objects.create(label='Agenda 2')
|
||||
pricing = Pricing.objects.create(label='Foo bar 1')
|
||||
|
@ -237,6 +247,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
|
|||
)
|
||||
agenda_pricing.agendas.add(agenda1, agenda2)
|
||||
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),
|
||||
|
@ -251,6 +262,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
|
|||
draft=True,
|
||||
)
|
||||
other_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),
|
||||
|
@ -365,6 +377,18 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
|
|||
pool=other_pool,
|
||||
from_injected_line=injected_line7,
|
||||
)
|
||||
# nok, other regie
|
||||
InjectedLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 15),
|
||||
slug='event-2022-09-15',
|
||||
label='Event 2022-09-15',
|
||||
quantity=3,
|
||||
unit_amount=1.5,
|
||||
total_amount=4.5,
|
||||
user_external_id='user:1',
|
||||
payer_external_id='payer:1',
|
||||
regie=other_regie,
|
||||
)
|
||||
|
||||
# no agendas
|
||||
assert (
|
||||
|
@ -665,6 +689,7 @@ def test_get_invoice_lines_for_user_check_status(mock_pricing_data_event, mock_s
|
|||
|
||||
@mock.patch('lingo.invoicing.utils.get_check_status')
|
||||
def test_get_invoice_lines_for_user_check_status_agenda_pricing_dates(mock_status):
|
||||
regie = Regie.objects.create(label='Regie')
|
||||
agenda = Agenda.objects.create(label='Agenda')
|
||||
pricing = Pricing.objects.create(label='Foo bar')
|
||||
agenda_pricing1 = AgendaPricing.objects.create(
|
||||
|
@ -687,6 +712,7 @@ def test_get_invoice_lines_for_user_check_status_agenda_pricing_dates(mock_statu
|
|||
)
|
||||
agenda_pricing3.agendas.add(agenda)
|
||||
campaign = Campaign.objects.create(
|
||||
regie=regie,
|
||||
date_start=datetime.date(2022, 1, 1),
|
||||
date_end=datetime.date(2023, 1, 1),
|
||||
date_issue=datetime.date(2023, 1, 31),
|
||||
|
@ -799,6 +825,7 @@ def test_get_invoice_lines_for_user_check_status_agenda_pricing_dates(mock_statu
|
|||
@mock.patch('lingo.invoicing.utils.get_check_status')
|
||||
@mock.patch('lingo.pricing.models.AgendaPricing.get_pricing_data_for_event')
|
||||
def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data_event, mock_status):
|
||||
regie = Regie.objects.create(label='Regie')
|
||||
agenda = Agenda.objects.create(label='Agenda')
|
||||
pricing = Pricing.objects.create(label='Foo bar')
|
||||
agenda_pricing = AgendaPricing.objects.create(
|
||||
|
@ -808,6 +835,7 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data
|
|||
)
|
||||
agenda_pricing.agendas.add(agenda)
|
||||
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),
|
||||
|
@ -927,10 +955,12 @@ def test_get_invoice_lines_for_user_check_status_pricing_error(mock_pricing_data
|
|||
|
||||
@mock.patch('lingo.invoicing.utils.get_invoice_lines_for_user')
|
||||
def test_get_all_invoice_lines(mock_user_lines):
|
||||
regie = Regie.objects.create(label='Regie')
|
||||
agenda1 = Agenda.objects.create(label='Agenda 1')
|
||||
agenda2 = Agenda.objects.create(label='Agenda 2')
|
||||
Agenda.objects.create(label='Agenda 3')
|
||||
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),
|
||||
|
@ -1044,7 +1074,9 @@ def test_get_all_invoice_lines_queryset(mock_status):
|
|||
)
|
||||
agenda_pricing22.agendas.add(agenda2)
|
||||
|
||||
regie = Regie.objects.create(label='Regie')
|
||||
campaign = Campaign.objects.create(
|
||||
regie=regie,
|
||||
date_start=datetime.date(2022, 9, 1),
|
||||
date_end=datetime.date(2022, 11, 1),
|
||||
date_issue=datetime.date(2022, 11, 30),
|
||||
|
@ -1109,14 +1141,10 @@ def test_get_all_invoice_lines_queryset(mock_status):
|
|||
|
||||
|
||||
def test_generate_invoices_from_lines():
|
||||
regie1 = Regie.objects.create(label='Regie 1')
|
||||
regie2 = Regie.objects.create(label='Regie 2')
|
||||
agenda1 = Agenda.objects.create(label='Agenda 1', regie=regie1)
|
||||
agenda2 = Agenda.objects.create(label='Agenda 2', regie=regie2)
|
||||
agenda3 = Agenda.objects.create(label='Agenda 3', regie=regie1)
|
||||
agenda4 = Agenda.objects.create(label='Agenda 4') # regie not configured
|
||||
regie = Regie.objects.create(label='Regie')
|
||||
|
||||
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),
|
||||
|
@ -1203,17 +1231,6 @@ def test_generate_invoices_from_lines():
|
|||
status='success',
|
||||
pool=pool,
|
||||
)
|
||||
line6 = DraftInvoiceLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
event={'agenda': 'agenda-4'}, # regie not configured
|
||||
quantity=1,
|
||||
unit_amount=6,
|
||||
total_amount=6,
|
||||
user_external_id='user:1',
|
||||
payer_external_id='user:1',
|
||||
status='success',
|
||||
pool=pool,
|
||||
)
|
||||
injected_line = InjectedLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
slug='event-2022-09-01',
|
||||
|
@ -1223,9 +1240,9 @@ def test_generate_invoices_from_lines():
|
|||
total_amount=7,
|
||||
user_external_id='user:1',
|
||||
payer_external_id='user:1',
|
||||
regie=regie1,
|
||||
regie=regie,
|
||||
)
|
||||
line7 = DraftInvoiceLine.objects.create(
|
||||
line6 = DraftInvoiceLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=1,
|
||||
unit_amount=7,
|
||||
|
@ -1238,57 +1255,30 @@ def test_generate_invoices_from_lines():
|
|||
)
|
||||
|
||||
invoices = utils.generate_invoices_from_lines(
|
||||
agendas=[],
|
||||
all_lines=[line_error, line1, line2, line3, line4, line5, line6],
|
||||
pool=pool,
|
||||
)
|
||||
assert len(invoices) == 0
|
||||
|
||||
with pytest.raises(RegieNotConfigured) as excinfo:
|
||||
invoices = utils.generate_invoices_from_lines(
|
||||
agendas=[agenda1, agenda2, agenda3, agenda4],
|
||||
all_lines=[line_error, line1, line2, line3, line4, line5, line6],
|
||||
pool=pool,
|
||||
)
|
||||
assert '%s' % excinfo.value == 'Regie not configured on agenda-4'
|
||||
assert len(invoices) == 0
|
||||
|
||||
line6.delete()
|
||||
invoices = utils.generate_invoices_from_lines(
|
||||
agendas=[agenda1, agenda2, agenda3, agenda4],
|
||||
all_lines=[line_error, line1, line2, line3, line4, line5, line7],
|
||||
pool=pool,
|
||||
)
|
||||
assert len(invoices) == 3
|
||||
invoice1, invoice2, invoice3 = invoices
|
||||
assert len(invoices) == 2
|
||||
invoice1, invoice2 = invoices
|
||||
# refresh total_amount field (triggered)
|
||||
invoice1.refresh_from_db()
|
||||
invoice2.refresh_from_db()
|
||||
invoice3.refresh_from_db()
|
||||
assert isinstance(invoice1, DraftInvoice)
|
||||
assert invoice1.label == 'Invoice from 2022-09-01 to 2022-09-30'
|
||||
assert invoice1.total_amount == 15
|
||||
assert invoice1.total_amount == 18
|
||||
assert invoice1.date_issue == datetime.date(2022, 10, 31)
|
||||
assert invoice1.regie == regie1
|
||||
assert invoice1.regie == regie
|
||||
assert invoice1.payer == 'user:1'
|
||||
assert invoice1.pool == pool
|
||||
assert list(invoice1.lines.order_by('pk')) == [line1, line2, line5, line7]
|
||||
assert list(invoice1.lines.order_by('pk')) == [line1, line2, line3, line5, line6]
|
||||
assert isinstance(invoice2, DraftInvoice)
|
||||
assert invoice2.label == 'Invoice from 2022-09-01 to 2022-09-30'
|
||||
assert invoice2.total_amount == 3
|
||||
assert invoice2.total_amount == 4
|
||||
assert invoice2.date_issue == datetime.date(2022, 10, 31)
|
||||
assert invoice2.regie == regie2
|
||||
assert invoice2.payer == 'user:1'
|
||||
assert invoice2.regie == regie
|
||||
assert invoice2.payer == 'user:2'
|
||||
assert invoice2.pool == pool
|
||||
assert list(invoice2.lines.order_by('pk')) == [line3]
|
||||
assert isinstance(invoice3, DraftInvoice)
|
||||
assert invoice3.label == 'Invoice from 2022-09-01 to 2022-09-30'
|
||||
assert invoice3.total_amount == 4
|
||||
assert invoice3.date_issue == datetime.date(2022, 10, 31)
|
||||
assert invoice3.regie == regie2
|
||||
assert invoice3.payer == 'user:2'
|
||||
assert invoice3.pool == pool
|
||||
assert list(invoice3.lines.order_by('pk')) == [line4]
|
||||
assert list(invoice2.lines.order_by('pk')) == [line4]
|
||||
|
||||
|
||||
@mock.patch('lingo.invoicing.utils.get_agendas')
|
||||
|
@ -1296,10 +1286,12 @@ def test_generate_invoices_from_lines():
|
|||
@mock.patch('lingo.invoicing.utils.get_all_invoice_lines')
|
||||
@mock.patch('lingo.invoicing.utils.generate_invoices_from_lines')
|
||||
def test_generate_invoices(mock_generate, mock_lines, mock_users, mock_agendas):
|
||||
regie = Regie.objects.create(label='Regie')
|
||||
agenda1 = Agenda.objects.create(label='Agenda 1')
|
||||
agenda2 = Agenda.objects.create(label='Agenda 2')
|
||||
Agenda.objects.create(label='Agenda 3')
|
||||
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),
|
||||
|
@ -1330,7 +1322,6 @@ def test_generate_invoices(mock_generate, mock_lines, mock_users, mock_agendas):
|
|||
]
|
||||
assert mock_generate.call_args_list == [
|
||||
mock.call(
|
||||
agendas=[agenda1, agenda2],
|
||||
all_lines=['foo', 'baz'],
|
||||
pool=pool,
|
||||
)
|
||||
|
@ -1342,10 +1333,12 @@ def test_generate_invoices(mock_generate, mock_lines, mock_users, mock_agendas):
|
|||
@mock.patch('lingo.invoicing.utils.get_all_invoice_lines')
|
||||
@mock.patch('lingo.invoicing.utils.generate_invoices_from_lines')
|
||||
def test_generate_invoices_errors(mock_generate, mock_lines, mock_users, mock_agendas):
|
||||
regie = Regie.objects.create(label='Regie')
|
||||
agenda1 = Agenda.objects.create(label='Agenda 1')
|
||||
agenda2 = Agenda.objects.create(label='Agenda 2')
|
||||
Agenda.objects.create(label='Agenda 3')
|
||||
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),
|
||||
|
@ -1358,41 +1351,43 @@ def test_generate_invoices_errors(mock_generate, mock_lines, mock_users, mock_ag
|
|||
assert pool.status == 'failed'
|
||||
assert pool.exception == 'foo bar'
|
||||
|
||||
mock_users.side_effect = None
|
||||
mock_users.return_value = ['foo', 'bar']
|
||||
mock_lines.side_effect = RegieNotConfigured('foo baz')
|
||||
campaign.generate()
|
||||
pool = Pool.objects.latest('pk')
|
||||
assert pool.status == 'failed'
|
||||
assert pool.exception == 'foo baz'
|
||||
|
||||
|
||||
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'
|
||||
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')
|
||||
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')
|
||||
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', '--date-issue=bad-value')
|
||||
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')
|
||||
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
|
||||
|
@ -1400,44 +1395,56 @@ def test_generate_invoices_cmd():
|
|||
mock_generate.reset_mock()
|
||||
|
||||
# again
|
||||
call_command('generate_invoices', '2022-09-01', '2022-10-01')
|
||||
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')
|
||||
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')
|
||||
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', '--date-issue=2022-10-31')
|
||||
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')
|
||||
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()
|
||||
regie1 = Regie.objects.create(label='Regie1')
|
||||
regie2 = Regie.objects.create(label='Regie2')
|
||||
regie = Regie.objects.create(label='Regie')
|
||||
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),
|
||||
|
@ -1453,6 +1460,7 @@ def test_promote_pool():
|
|||
status='completed',
|
||||
)
|
||||
other_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),
|
||||
|
@ -1463,7 +1471,7 @@ def test_promote_pool():
|
|||
)
|
||||
|
||||
invoice1 = DraftInvoice.objects.create(
|
||||
date_issue=datetime.date.today(), regie=regie1, pool=pool, payer='payer:1'
|
||||
date_issue=datetime.date.today(), regie=regie, pool=pool, payer='payer:1'
|
||||
)
|
||||
line11 = DraftInvoiceLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -1490,7 +1498,7 @@ def test_promote_pool():
|
|||
total_amount=2,
|
||||
user_external_id='user:2',
|
||||
payer_external_id='payer:1',
|
||||
regie=regie1,
|
||||
regie=regie,
|
||||
)
|
||||
line12 = DraftInvoiceLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -1508,7 +1516,7 @@ def test_promote_pool():
|
|||
pool=pool,
|
||||
)
|
||||
invoice2 = DraftInvoice.objects.create(
|
||||
date_issue=datetime.date.today(), regie=regie1, pool=pool, payer='payer:2'
|
||||
date_issue=datetime.date.today(), regie=regie, pool=pool, payer='payer:2'
|
||||
)
|
||||
injected_line21 = InjectedLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -1519,7 +1527,7 @@ def test_promote_pool():
|
|||
total_amount=1,
|
||||
user_external_id='user:2',
|
||||
payer_external_id='payer:2',
|
||||
regie=regie1,
|
||||
regie=regie,
|
||||
)
|
||||
line21 = DraftInvoiceLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -1578,11 +1586,11 @@ def test_promote_pool():
|
|||
)
|
||||
|
||||
invoice3 = DraftInvoice.objects.create(
|
||||
date_issue=datetime.date.today(), regie=regie2, pool=pool, payer='payer:1'
|
||||
date_issue=datetime.date.today(), regie=regie, pool=pool, payer='payer:1'
|
||||
)
|
||||
|
||||
old_invoice = DraftInvoice.objects.create(
|
||||
date_issue=datetime.date.today(), regie=regie1, pool=old_pool, payer='payer:1'
|
||||
date_issue=datetime.date.today(), regie=regie, pool=old_pool, payer='payer:1'
|
||||
)
|
||||
DraftInvoiceLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -1607,7 +1615,7 @@ def test_promote_pool():
|
|||
total_amount=2,
|
||||
user_external_id='user:2',
|
||||
payer_external_id='payer:1',
|
||||
regie=regie1,
|
||||
regie=regie,
|
||||
)
|
||||
DraftInvoiceLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -1626,7 +1634,7 @@ def test_promote_pool():
|
|||
)
|
||||
|
||||
other_invoice = DraftInvoice.objects.create(
|
||||
date_issue=datetime.date.today(), regie=regie1, pool=other_pool, payer='payer:1'
|
||||
date_issue=datetime.date.today(), regie=regie, pool=other_pool, payer='payer:1'
|
||||
)
|
||||
DraftInvoiceLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -1651,7 +1659,7 @@ def test_promote_pool():
|
|||
total_amount=2,
|
||||
user_external_id='user:2',
|
||||
payer_external_id='payer:1',
|
||||
regie=regie1,
|
||||
regie=regie,
|
||||
)
|
||||
DraftInvoiceLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -1692,8 +1700,7 @@ def test_promote_pool():
|
|||
assert Invoice.objects.count() == 3
|
||||
assert InvoiceLine.objects.count() == 6
|
||||
assert InjectedLine.objects.count() == 4
|
||||
assert Counter.objects.get(regie=regie1, name=today.strftime('%y')).value == 2
|
||||
assert Counter.objects.get(regie=regie2, name=today.strftime('%y')).value == 1
|
||||
assert Counter.objects.get(regie=regie, name=today.strftime('%y')).value == 3
|
||||
|
||||
test_counts()
|
||||
|
||||
|
@ -1706,12 +1713,12 @@ def test_promote_pool():
|
|||
|
||||
final_invoice1 = Invoice.objects.order_by('pk')[0]
|
||||
assert final_invoice1.date_issue == invoice1.date_issue
|
||||
assert final_invoice1.regie == regie1
|
||||
assert final_invoice1.regie == regie
|
||||
assert final_invoice1.pool == final_pool
|
||||
assert final_invoice1.payer == invoice1.payer
|
||||
assert final_invoice1.total_amount == invoice1.total_amount == 3
|
||||
assert final_invoice1.number == 1
|
||||
assert final_invoice1.formatted_number == 'F%02d-%s-0000001' % (regie1.pk, today.strftime('%y-%m'))
|
||||
assert final_invoice1.formatted_number == 'F%02d-%s-0000001' % (regie.pk, today.strftime('%y-%m'))
|
||||
|
||||
final_line11 = InvoiceLine.objects.order_by('pk')[0]
|
||||
assert final_line11.event_date == line11.event_date
|
||||
|
@ -1749,12 +1756,12 @@ def test_promote_pool():
|
|||
|
||||
final_invoice2 = Invoice.objects.order_by('pk')[1]
|
||||
assert final_invoice2.date_issue == invoice2.date_issue
|
||||
assert final_invoice2.regie == regie1
|
||||
assert final_invoice2.regie == regie
|
||||
assert final_invoice2.pool == final_pool
|
||||
assert final_invoice2.payer == invoice2.payer
|
||||
assert final_invoice2.total_amount == invoice2.total_amount == 3
|
||||
assert final_invoice2.number == 2
|
||||
assert final_invoice2.formatted_number == 'F%02d-%s-0000002' % (regie1.pk, today.strftime('%y-%m'))
|
||||
assert final_invoice2.formatted_number == 'F%02d-%s-0000002' % (regie.pk, today.strftime('%y-%m'))
|
||||
|
||||
final_line21 = InvoiceLine.objects.order_by('pk')[2]
|
||||
assert final_line21.event_date == line21.event_date
|
||||
|
@ -1824,12 +1831,12 @@ def test_promote_pool():
|
|||
|
||||
final_invoice3 = Invoice.objects.order_by('pk')[2]
|
||||
assert final_invoice3.date_issue == invoice3.date_issue
|
||||
assert final_invoice3.regie == regie2
|
||||
assert final_invoice3.regie == regie
|
||||
assert final_invoice3.pool == final_pool
|
||||
assert final_invoice3.payer == invoice3.payer
|
||||
assert final_invoice3.total_amount == invoice3.total_amount == 0
|
||||
assert final_invoice3.number == 1
|
||||
assert final_invoice3.formatted_number == 'F%02d-%s-0000001' % (regie2.pk, today.strftime('%y-%m'))
|
||||
assert final_invoice3.number == 3
|
||||
assert final_invoice3.formatted_number == 'F%02d-%s-0000003' % (regie.pk, today.strftime('%y-%m'))
|
||||
|
||||
with pytest.raises(PoolPromotionError) as excinfo:
|
||||
old_pool.promote()
|
||||
|
|
|
@ -23,6 +23,7 @@ def test_invoice_total_amount(draft):
|
|||
line_model = DraftInvoiceLine if draft else InvoiceLine
|
||||
|
||||
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),
|
||||
|
|
Ok, je comprends la nécessité du nettoyage ici, mais n’y a-t-il pas des instances en recettes où des données ont déjà été créées à des fins de tests, par Stef ou quelqu’un d’autre, et qu’il faudrait sauvegarder dans un coin avant d’exécuter cette migration ?
non pas de données à conserver, et c'était écrit dans la description du ticket :)
Arf désolé j’ai loupé ça.