Compare commits
10 Commits
2939d3f739
...
3b3dcf1c7f
Author | SHA1 | Date |
---|---|---|
Lauréline Guérin | 3b3dcf1c7f | |
Lauréline Guérin | 904203c808 | |
Lauréline Guérin | b48de48412 | |
Lauréline Guérin | 9352f2d0c7 | |
Lauréline Guérin | 73f2cafd40 | |
Lauréline Guérin | 2f9f811fe2 | |
Lauréline Guérin | 5d7b9e9a66 | |
Lauréline Guérin | 6e51ef0545 | |
Lauréline Guérin | 21045178b6 | |
Lauréline Guérin | 6f45045d85 |
|
@ -17,6 +17,7 @@
|
|||
import datetime
|
||||
import uuid
|
||||
|
||||
from django.db.models import Q
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
@ -402,7 +403,13 @@ class RefundSerializer(serializers.ModelSerializer):
|
|||
|
||||
def validate_credit(self, value):
|
||||
try:
|
||||
credit = Credit.objects.get(uuid=value, regie=self.regie)
|
||||
credit = Credit.objects.get(
|
||||
Q(pool__isnull=True) | Q(pool__campaign__finalized=True),
|
||||
uuid=value,
|
||||
regie=self.regie,
|
||||
date_publication__lte=datetime.date.today(),
|
||||
cancelled_at__isnull=True,
|
||||
)
|
||||
except Credit.DoesNotExist:
|
||||
raise ValidationError(_('Unknown credit.'))
|
||||
if credit.remaining_amount == 0:
|
||||
|
|
|
@ -399,9 +399,11 @@ class InvoicingDraftInvoiceClose(APIView):
|
|||
def post(self, request, regie_identifier, invoice_identifier):
|
||||
regie = get_object_or_404(Regie, slug=regie_identifier)
|
||||
invoice = get_object_or_404(DraftInvoice, regie=regie, uuid=invoice_identifier, pool__isnull=True)
|
||||
final_invoice = invoice.promote()
|
||||
final_object = invoice.promote()
|
||||
|
||||
return Response({'data': {'invoice_id': str(final_invoice.uuid)}})
|
||||
if isinstance(final_object, Invoice):
|
||||
return Response({'data': {'invoice_id': str(final_object.uuid)}})
|
||||
return Response({'data': {'credit_id': str(final_object.uuid)}})
|
||||
|
||||
|
||||
invoicing_draft_invoice_close = InvoicingDraftInvoiceClose.as_view()
|
||||
|
@ -517,9 +519,12 @@ class InvoicingCredits(PayerMixin, APIView):
|
|||
payer_external_id=request.GET.get('payer_external_id'),
|
||||
)
|
||||
return Credit.objects.filter(
|
||||
Q(pool__isnull=True) | Q(pool__campaign__finalized=True),
|
||||
regie=regie,
|
||||
remaining_amount__gt=0,
|
||||
payer_external_id=payer_external_id,
|
||||
date_publication__lte=datetime.date.today(),
|
||||
cancelled_at__isnull=True,
|
||||
).order_by('-created_at')
|
||||
|
||||
def get(self, request, regie_identifier):
|
||||
|
@ -557,9 +562,12 @@ class InvoicingHistoryCredits(InvoicingCredits):
|
|||
payer_external_id=request.GET.get('payer_external_id'),
|
||||
)
|
||||
return Credit.objects.filter(
|
||||
Q(pool__isnull=True) | Q(pool__campaign__finalized=True),
|
||||
regie=regie,
|
||||
remaining_amount=0,
|
||||
payer_external_id=payer_external_id,
|
||||
date_publication__lte=datetime.date.today(),
|
||||
cancelled_at__isnull=True,
|
||||
).order_by('-created_at')
|
||||
|
||||
|
||||
|
@ -579,9 +587,12 @@ class InvoicingCreditPDF(PayerMixin, APIView):
|
|||
)
|
||||
credit = get_object_or_404(
|
||||
Credit,
|
||||
Q(pool__isnull=True) | Q(pool__campaign__finalized=True),
|
||||
uuid=credit_identifier,
|
||||
regie=regie,
|
||||
payer_external_id=payer_external_id,
|
||||
date_publication__lte=datetime.date.today(),
|
||||
cancelled_at__isnull=True,
|
||||
)
|
||||
result = credit.html()
|
||||
html = HTML(string=result)
|
||||
|
|
|
@ -164,7 +164,12 @@ class Basket(models.Model):
|
|||
if self.total_amount < 0:
|
||||
return 0
|
||||
credit_qs = Credit.objects.filter(
|
||||
remaining_amount__gt=0, regie=self.regie, payer_external_id=self.payer_external_id
|
||||
models.Q(pool__isnull=True) | models.Q(pool__campaign__finalized=True),
|
||||
date_publication__lte=datetime.date.today(),
|
||||
cancelled_at__isnull=True,
|
||||
remaining_amount__gt=0,
|
||||
regie=self.regie,
|
||||
payer_external_id=self.payer_external_id,
|
||||
)
|
||||
available_credit = sum(c.remaining_amount for c in credit_qs)
|
||||
return -min(self.total_amount, available_credit)
|
||||
|
|
|
@ -1080,6 +1080,16 @@ class RegieCreditFilterSet(AgendaFieldsFilterSetMixin, django_filters.FilterSet)
|
|||
],
|
||||
method='filter_assigned',
|
||||
)
|
||||
cancelled = django_filters.ChoiceFilter(
|
||||
label=_('Cancelled'),
|
||||
widget=forms.RadioSelect,
|
||||
empty_label=_('all'),
|
||||
choices=[
|
||||
('yes', _('Yes')),
|
||||
('no', _('No')),
|
||||
],
|
||||
method='filter_cancelled',
|
||||
)
|
||||
agenda = django_filters.ChoiceFilter(
|
||||
label=_('Activity'),
|
||||
empty_label=_('all'),
|
||||
|
@ -1137,6 +1147,13 @@ class RegieCreditFilterSet(AgendaFieldsFilterSetMixin, django_filters.FilterSet)
|
|||
return queryset.filter(assigned_amount=0)
|
||||
return queryset
|
||||
|
||||
def filter_cancelled(self, queryset, name, value):
|
||||
if not value:
|
||||
return queryset
|
||||
if value == 'yes':
|
||||
return queryset.filter(cancelled_at__isnull=False)
|
||||
return queryset.filter(cancelled_at__isnull=True)
|
||||
|
||||
def filter_agenda(self, queryset, name, value):
|
||||
if not value:
|
||||
return queryset
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import datetime
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('invoicing', '0087_cancellation_reason'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='credit',
|
||||
name='date_publication',
|
||||
field=models.DateField(default=datetime.date.today, verbose_name='Publication date'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='credit',
|
||||
name='pool',
|
||||
field=models.ForeignKey(
|
||||
null=True, on_delete=django.db.models.deletion.PROTECT, to='invoicing.pool'
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='journalline',
|
||||
name='credit_line',
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name='journal_lines',
|
||||
to='invoicing.creditline',
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,40 @@
|
|||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('invoicing', '0088_credit_from_pool'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='credit',
|
||||
name='cancellation_description',
|
||||
field=models.TextField(blank=True, verbose_name='Description'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='credit',
|
||||
name='cancellation_reason',
|
||||
field=models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to='invoicing.invoicecancellationreason',
|
||||
verbose_name='Cancellation reason',
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='credit',
|
||||
name='cancelled_at',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='credit',
|
||||
name='cancelled_by',
|
||||
field=models.ForeignKey(
|
||||
null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL
|
||||
),
|
||||
),
|
||||
]
|
|
@ -837,12 +837,13 @@ class DraftJournalLine(AbstractJournalLine):
|
|||
'invoicing.DraftInvoiceLine', on_delete=models.PROTECT, null=True, related_name='journal_lines'
|
||||
)
|
||||
|
||||
def promote(self, pool=None, invoice_line=None):
|
||||
def promote(self, pool=None, invoice_line=None, credit_line=None):
|
||||
final_line = copy.deepcopy(self)
|
||||
final_line.__class__ = JournalLine
|
||||
final_line.pk = None
|
||||
final_line.pool = pool
|
||||
final_line.invoice_line = invoice_line
|
||||
final_line.credit_line = credit_line
|
||||
final_line.error_status = ''
|
||||
final_line.save()
|
||||
|
||||
|
@ -851,6 +852,9 @@ class JournalLine(AbstractJournalLine):
|
|||
invoice_line = models.ForeignKey(
|
||||
'invoicing.InvoiceLine', on_delete=models.PROTECT, null=True, related_name='journal_lines'
|
||||
)
|
||||
credit_line = models.ForeignKey(
|
||||
'invoicing.CreditLine', on_delete=models.PROTECT, null=True, related_name='journal_lines'
|
||||
)
|
||||
|
||||
|
||||
class Counter(models.Model):
|
||||
|
@ -891,6 +895,9 @@ class AbstractInvoiceObject(models.Model):
|
|||
payer_last_name = models.CharField(max_length=250)
|
||||
payer_address = models.TextField()
|
||||
|
||||
date_publication = models.DateField(_('Publication date'))
|
||||
pool = models.ForeignKey(Pool, on_delete=models.PROTECT, null=True)
|
||||
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
|
@ -909,15 +916,12 @@ class AbstractInvoiceObject(models.Model):
|
|||
|
||||
|
||||
class AbstractInvoice(AbstractInvoiceObject):
|
||||
date_publication = models.DateField(_('Publication date'))
|
||||
date_payment_deadline = models.DateField(_('Payment deadline'))
|
||||
date_due = models.DateField(_('Due date'))
|
||||
date_debit = models.DateField(_('Debit date'), null=True)
|
||||
payer_demat = models.BooleanField(default=False)
|
||||
payer_direct_debit = models.BooleanField(default=False)
|
||||
|
||||
pool = models.ForeignKey(Pool, on_delete=models.PROTECT, null=True)
|
||||
|
||||
payment_callback_url = models.URLField(blank=True)
|
||||
|
||||
class Meta:
|
||||
|
@ -998,7 +1002,7 @@ class DraftInvoice(AbstractInvoice):
|
|||
def promote(self, pool=None):
|
||||
if self.total_amount >= 0:
|
||||
return self.promote_into_invoice(pool=pool)
|
||||
return self.promote_into_credit()
|
||||
return self.promote_into_credit(pool=pool)
|
||||
|
||||
def promote_into_invoice(self, pool=None):
|
||||
final_invoice = copy.deepcopy(self)
|
||||
|
@ -1020,19 +1024,24 @@ class DraftInvoice(AbstractInvoice):
|
|||
|
||||
return final_invoice
|
||||
|
||||
def promote_into_credit(self):
|
||||
def promote_into_credit(self, pool=None):
|
||||
credit = copy.deepcopy(self)
|
||||
credit.__class__ = Credit
|
||||
credit.pk = None
|
||||
credit.uuid = uuid.uuid4()
|
||||
credit.pool = pool
|
||||
credit.set_number()
|
||||
credit.assigned_amount = 0
|
||||
credit.remaining_amount = 0
|
||||
credit.label = _('Credit from %s') % datetime.date.today().strftime('%d/%m/%Y')
|
||||
credit.cancelled_at = None
|
||||
credit.cancelled_by = None
|
||||
credit.cancellation_reason = None
|
||||
credit.cancellation_description = ''
|
||||
credit.save()
|
||||
|
||||
for line in self.lines.all().order_by('pk'):
|
||||
line.promote_into_credit(credit=credit)
|
||||
line.promote_into_credit(pool=pool, credit=credit)
|
||||
|
||||
return credit
|
||||
|
||||
|
@ -1058,6 +1067,19 @@ class InvoiceCancellationReason(models.Model):
|
|||
return slugify(self.label)
|
||||
|
||||
|
||||
def get_cancellation_info(obj):
|
||||
result = []
|
||||
if not obj.cancelled_at:
|
||||
return result
|
||||
result.append((_('Cancelled on'), obj.cancelled_at.strftime('%d/%m/%Y %H:%M')))
|
||||
if obj.cancelled_by:
|
||||
result.append((_('Cancelled by'), obj.cancelled_by))
|
||||
result.append((_('Reason'), obj.cancellation_reason))
|
||||
if obj.cancellation_description:
|
||||
result.append((_('Description'), linebreaksbr(obj.cancellation_description)))
|
||||
return result
|
||||
|
||||
|
||||
class Invoice(AbstractInvoice):
|
||||
number = models.PositiveIntegerField(default=0)
|
||||
formatted_number = models.CharField(max_length=200)
|
||||
|
@ -1126,16 +1148,7 @@ class Invoice(AbstractInvoice):
|
|||
return sorted(invoice_payments.values(), key=lambda a: a.payment.created_at)
|
||||
|
||||
def get_cancellation_info(self):
|
||||
result = []
|
||||
if not self.cancelled_at:
|
||||
return result
|
||||
result.append((_('Cancelled on'), self.cancelled_at.strftime('%d/%m/%Y %H:%M')))
|
||||
if self.cancelled_by:
|
||||
result.append((_('Cancelled by'), self.cancelled_by))
|
||||
result.append((_('Reason'), self.cancellation_reason))
|
||||
if self.cancellation_description:
|
||||
result.append((_('Description'), linebreaksbr(self.cancellation_description)))
|
||||
return result
|
||||
return get_cancellation_info(self)
|
||||
|
||||
|
||||
class Credit(AbstractInvoiceObject):
|
||||
|
@ -1143,6 +1156,12 @@ class Credit(AbstractInvoiceObject):
|
|||
formatted_number = models.CharField(max_length=200)
|
||||
assigned_amount = models.DecimalField(max_digits=9, decimal_places=2, default=0)
|
||||
remaining_amount = models.DecimalField(max_digits=9, decimal_places=2, default=0)
|
||||
cancelled_at = models.DateTimeField(null=True)
|
||||
cancelled_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True)
|
||||
cancellation_reason = models.ForeignKey(
|
||||
InvoiceCancellationReason, verbose_name=_('Cancellation reason'), on_delete=models.PROTECT, null=True
|
||||
)
|
||||
cancellation_description = models.TextField(_('Description'), blank=True)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
|
@ -1207,6 +1226,9 @@ class Credit(AbstractInvoiceObject):
|
|||
}
|
||||
return template.render(context)
|
||||
|
||||
def get_cancellation_info(self):
|
||||
return get_cancellation_info(self)
|
||||
|
||||
|
||||
class AbstractInvoiceLineObject(models.Model):
|
||||
uuid = models.UUIDField(default=uuid.uuid4, editable=False, null=True)
|
||||
|
@ -1264,7 +1286,7 @@ class AbstractInvoiceLine(AbstractInvoiceLineObject):
|
|||
class DraftInvoiceLine(AbstractInvoiceLine):
|
||||
invoice = models.ForeignKey(DraftInvoice, on_delete=models.PROTECT, null=True, related_name='lines')
|
||||
|
||||
def promote(self, pool=None, invoice=None):
|
||||
def promote(self, invoice, pool=None):
|
||||
final_line = copy.deepcopy(self)
|
||||
final_line.__class__ = InvoiceLine
|
||||
final_line.pk = None
|
||||
|
@ -1278,7 +1300,7 @@ class DraftInvoiceLine(AbstractInvoiceLine):
|
|||
for line in self.journal_lines.all().order_by('pk'):
|
||||
line.promote(pool=pool, invoice_line=final_line)
|
||||
|
||||
def promote_into_credit(self, credit=None):
|
||||
def promote_into_credit(self, credit, pool=None):
|
||||
credit_line = copy.deepcopy(self)
|
||||
credit_line.__class__ = CreditLine
|
||||
credit_line.pk = None
|
||||
|
@ -1288,6 +1310,9 @@ class DraftInvoiceLine(AbstractInvoiceLine):
|
|||
credit_line.remaining_amount = 0
|
||||
credit_line.save()
|
||||
|
||||
for line in self.journal_lines.all().order_by('pk'):
|
||||
line.promote(pool=pool, credit_line=credit_line)
|
||||
|
||||
|
||||
class InvoiceLine(AbstractInvoiceLine):
|
||||
invoice = models.ForeignKey(Invoice, on_delete=models.PROTECT, null=True, related_name='lines')
|
||||
|
@ -1592,16 +1617,7 @@ class Payment(models.Model):
|
|||
return result
|
||||
|
||||
def get_cancellation_info(self):
|
||||
result = []
|
||||
if not self.cancelled_at:
|
||||
return result
|
||||
result.append((_('Cancelled on'), self.cancelled_at.strftime('%d/%m/%Y %H:%M')))
|
||||
if self.cancelled_by:
|
||||
result.append((_('Cancelled by'), self.cancelled_by))
|
||||
result.append((_('Reason'), self.cancellation_reason))
|
||||
if self.cancellation_description:
|
||||
result.append((_('Description'), linebreaksbr(self.cancellation_description)))
|
||||
return result
|
||||
return get_cancellation_info(self)
|
||||
|
||||
def get_invoice_payments(self):
|
||||
if hasattr(self, 'prefetched_invoicelinepayments'):
|
||||
|
@ -1691,11 +1707,15 @@ class CreditAssignment(models.Model):
|
|||
|
||||
@classmethod
|
||||
def make_assignments(cls, regie, basket):
|
||||
credit_qs = (
|
||||
Credit.objects.select_for_update()
|
||||
.filter(remaining_amount__gt=0, regie=regie, payer_external_id=basket.payer_external_id)
|
||||
.order_by('pk')
|
||||
credit_qs = Credit.objects.filter(
|
||||
models.Q(pool__isnull=True) | models.Q(pool__campaign__finalized=True),
|
||||
date_publication__lte=datetime.date.today(),
|
||||
cancelled_at__isnull=True,
|
||||
remaining_amount__gt=0,
|
||||
regie=regie,
|
||||
payer_external_id=basket.payer_external_id,
|
||||
)
|
||||
credit_qs = Credit.objects.select_for_update().filter(pk__in=credit_qs.values('id')).order_by('pk')
|
||||
with transaction.atomic():
|
||||
available_credit = sum(c.remaining_amount for c in credit_qs)
|
||||
amount_to_assign = min(available_credit, basket.invoice.remaining_amount)
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
{% for reason in invoice_reason_list %}
|
||||
<li>
|
||||
<a href="{% url 'lingo-manager-invoicing-invoice-cancellation-reason-edit' reason.pk %}">{{ reason }}{% if reason.disabled %}<span class="extra-info"> ({% trans "disabled" %})</span>{% endif %}</a>
|
||||
{% if not reason.invoice_set.exists %}
|
||||
{% if not reason.invoice_set.exists and not reason.credit_set.exists %}
|
||||
<a class="delete" rel="popup" href="{% url 'lingo-manager-invoicing-invoice-cancellation-reason-delete' reason.pk %}">{% trans "delete"%}</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
|
|
|
@ -44,62 +44,73 @@
|
|||
<td></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr class="line" data-related-invoicing-element-id="{{ credit.pk }}">
|
||||
<th colspan="7" class="assignments">
|
||||
{% trans "Assignments" %}
|
||||
</th>
|
||||
</tr>
|
||||
<tr class="line" data-related-invoicing-element-id="{{ credit.pk }}">
|
||||
<td class="payment-num">{% trans "Payment" context 'payment' %}</td>
|
||||
<td colspan="4">{% trans "Date" context 'payment' %}</td>
|
||||
<td class="amount" colspan="2">{% trans "Amount" %}</td>
|
||||
</tr>
|
||||
{% for assignment in credit.creditassignment_set.all %}
|
||||
{% if not credit.cancelled_at %}
|
||||
<tr class="line" data-related-invoicing-element-id="{{ credit.pk }}">
|
||||
{% if assignment.payment %}
|
||||
<td>
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-payment-list' regie_pk=regie.pk %}?number={{ assignment.payment.formatted_number }}">{{ assignment.payment.formatted_number }}</a>
|
||||
</td>
|
||||
<td colspan="4">
|
||||
{{ assignment.payment.created_at|date:"DATETIME_FORMAT" }}
|
||||
</td>
|
||||
{% elif assignment.invoice %}
|
||||
<td>
|
||||
<i>{% trans "Pending..." %}</i>
|
||||
</td>
|
||||
<td colspan="4"></td>
|
||||
{% else %}
|
||||
<td>
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-refund-list' regie_pk=regie.pk %}?number={{ assignment.refund.formatted_number }}">{{ assignment.refund.formatted_number }} ({% trans "Refund" %})</a>
|
||||
</td>
|
||||
<td colspan="4">
|
||||
{{ assignment.refund.created_at|date:"DATETIME_FORMAT" }}
|
||||
</td>
|
||||
{% endif %}
|
||||
<td class="amount" colspan="2">
|
||||
{% blocktrans with amount=assignment.amount|floatformat:"2" %}{{ amount }}€{% endblocktrans %}
|
||||
</td>
|
||||
<th colspan="7" class="assignments">
|
||||
{% trans "Assignments" %}
|
||||
</th>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr class="line" data-related-invoicing-element-id="{{ credit.pk }}">
|
||||
<td colspan="7" class="no-payments">
|
||||
{% trans "No assignments for this credit" %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if credit.assigned_amount %}
|
||||
<tr class="line {% if not credit.remaining_amount%}last-line{% endif %}" data-related-invoicing-element-id="{{ credit.pk }}">
|
||||
<td colspan="2"></td>
|
||||
<td class="invoice-details" colspan="5">
|
||||
<i>{% trans "Assigned amount:" %} {% blocktrans with amount=credit.assigned_amount|floatformat:"2" %}{{ amount }}€{% endblocktrans %}</i>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if credit.remaining_amount %}
|
||||
<tr class="line last-line" data-related-invoicing-element-id="{{ credit.pk }}">
|
||||
<td colspan="2"></td>
|
||||
<td class="invoice-details" colspan="5">
|
||||
<i>{% trans "Remaining amount to assign:" %} {% blocktrans with amount=credit.remaining_amount|floatformat:"2" %}{{ amount }}€{% endblocktrans %}</i>
|
||||
</td>
|
||||
<td class="payment-num">{% trans "Payment" context 'payment' %}</td>
|
||||
<td colspan="4">{% trans "Date" context 'payment' %}</td>
|
||||
<td class="amount" colspan="2">{% trans "Amount" %}</td>
|
||||
</tr>
|
||||
{% for assignment in credit.creditassignment_set.all %}
|
||||
<tr class="line" data-related-invoicing-element-id="{{ credit.pk }}">
|
||||
{% if assignment.payment %}
|
||||
<td>
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-payment-list' regie_pk=regie.pk %}?number={{ assignment.payment.formatted_number }}">{{ assignment.payment.formatted_number }}</a>
|
||||
</td>
|
||||
<td colspan="4">
|
||||
{{ assignment.payment.created_at|date:"DATETIME_FORMAT" }}
|
||||
</td>
|
||||
{% elif assignment.invoice %}
|
||||
<td>
|
||||
<i>{% trans "Pending..." %}</i>
|
||||
</td>
|
||||
<td colspan="4"></td>
|
||||
{% else %}
|
||||
<td>
|
||||
<a href="{% url 'lingo-manager-invoicing-regie-refund-list' regie_pk=regie.pk %}?number={{ assignment.refund.formatted_number }}">{{ assignment.refund.formatted_number }} ({% trans "Refund" %})</a>
|
||||
</td>
|
||||
<td colspan="4">
|
||||
{{ assignment.refund.created_at|date:"DATETIME_FORMAT" }}
|
||||
</td>
|
||||
{% endif %}
|
||||
<td class="amount" colspan="2">
|
||||
{% blocktrans with amount=assignment.amount|floatformat:"2" %}{{ amount }}€{% endblocktrans %}
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr class="line" data-related-invoicing-element-id="{{ credit.pk }}">
|
||||
<td colspan="7" class="no-payments">
|
||||
{% trans "No assignments for this credit" %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% if credit.assigned_amount %}
|
||||
<tr class="line {% if not credit.remaining_amount%}last-line{% endif %}" data-related-invoicing-element-id="{{ credit.pk }}">
|
||||
<td colspan="2"></td>
|
||||
<td class="invoice-details" colspan="5">
|
||||
<i>{% trans "Assigned amount:" %} {% blocktrans with amount=credit.assigned_amount|floatformat:"2" %}{{ amount }}€{% endblocktrans %}</i>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% if credit.remaining_amount %}
|
||||
<tr class="line last-line" data-related-invoicing-element-id="{{ credit.pk }}">
|
||||
<td colspan="2"></td>
|
||||
<td class="invoice-details" colspan="5">
|
||||
<i>{% trans "Remaining amount to assign:" %} {% blocktrans with amount=credit.remaining_amount|floatformat:"2" %}{{ amount }}€{% endblocktrans %}</i>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% for label, value in credit.get_cancellation_info %}
|
||||
<tr class="line {% if forloop.last %}last-line{% endif %}" data-related-invoicing-element-id="{{ credit.pk }}">
|
||||
<td colspan="2"></td>
|
||||
<td class="invoice-details" colspan="5">
|
||||
<i>{% blocktrans %}{{ label }}:{% endblocktrans %} {{ value }}</i>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
|
|
@ -31,7 +31,9 @@
|
|||
{% for credit in object_list %}
|
||||
<tr class="credit untoggled" data-invoicing-element-id="{{ credit.pk }}" data-invoicing-element-lines-url="{% url 'lingo-manager-invoicing-regie-credit-line-list' regie_pk=regie.pk credit_pk=credit.pk %}">
|
||||
<td colspan="6">
|
||||
{% if credit.remaining_amount > 0 and credit.assigned_amount > 0 %}
|
||||
{% if credit.cancelled_at %}
|
||||
<span class="meta meta-error">{% trans "Cancelled" context "credit" %}</span>
|
||||
{% elif credit.remaining_amount > 0 and credit.assigned_amount > 0 %}
|
||||
<span class="meta meta-warning">{% trans "Partially assigned" %}</span>
|
||||
{% elif credit.remaining_amount == 0 %}
|
||||
<span class="meta meta-success">{% trans "Assigned" %}</span>
|
||||
|
|
|
@ -66,7 +66,7 @@ class InvoiceReasonDeleteView(DeleteView):
|
|||
model = InvoiceCancellationReason
|
||||
|
||||
def get_queryset(self):
|
||||
return InvoiceCancellationReason.objects.filter(invoice__isnull=True)
|
||||
return InvoiceCancellationReason.objects.filter(invoice__isnull=True, credit__isnull=True)
|
||||
|
||||
def get_success_url(self):
|
||||
return '%s#open:invoice' % reverse('lingo-manager-invoicing-cancellation-reason-list')
|
||||
|
|
|
@ -977,7 +977,7 @@ def test_detail_invoice(mock_payer, app, user):
|
|||
PaymentType.create_defaults(regie)
|
||||
app.get('/api/regie/foo/invoice/%s/' % str(uuid.uuid4()), status=404)
|
||||
|
||||
resp = app.get('/api/regie/foo/invoice/%s/' % str(uuid.uuid4()), params={'NameID': 'foobar'}, status=404)
|
||||
app.get('/api/regie/foo/invoice/%s/' % str(uuid.uuid4()), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
invoice = Invoice.objects.create(
|
||||
label='My invoice',
|
||||
|
@ -1027,14 +1027,14 @@ def test_detail_invoice(mock_payer, app, user):
|
|||
# publication date is in the future
|
||||
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
||||
invoice.save()
|
||||
resp = app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
# other regie
|
||||
other_regie = Regie.objects.create(label='Other Foo')
|
||||
invoice.date_publication = datetime.date.today()
|
||||
invoice.regie = other_regie
|
||||
invoice.save()
|
||||
resp = app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
# part of amount was already paid
|
||||
invoice.regie = regie
|
||||
|
@ -1108,7 +1108,7 @@ def test_detail_invoice(mock_payer, app, user):
|
|||
invoice_line_payment.amount = 1
|
||||
invoice_line_payment.save()
|
||||
mock_payer.return_value = 'payer:unknown'
|
||||
resp = app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
# campaign is not finalized
|
||||
mock_payer.return_value = 'payer:1'
|
||||
|
@ -1151,7 +1151,7 @@ def test_detail_invoice_for_payer(app, user):
|
|||
PaymentType.create_defaults(regie)
|
||||
app.get('/api/regie/foo/invoice/%s/' % str(uuid.uuid4()), status=404)
|
||||
|
||||
resp = app.get(
|
||||
app.get(
|
||||
'/api/regie/foo/invoice/%s/' % str(uuid.uuid4()), params={'payer_external_id': 'payer:1'}, status=404
|
||||
)
|
||||
|
||||
|
@ -1202,7 +1202,7 @@ def test_detail_invoice_for_payer(app, user):
|
|||
# publication date is in the future
|
||||
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
||||
invoice.save()
|
||||
resp = app.get(
|
||||
app.get(
|
||||
'/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'payer_external_id': 'payer:1'}, status=404
|
||||
)
|
||||
|
||||
|
@ -1211,7 +1211,7 @@ def test_detail_invoice_for_payer(app, user):
|
|||
invoice.date_publication = datetime.date.today()
|
||||
invoice.regie = other_regie
|
||||
invoice.save()
|
||||
resp = app.get(
|
||||
app.get(
|
||||
'/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'payer_external_id': 'payer:1'}, status=404
|
||||
)
|
||||
|
||||
|
@ -1331,9 +1331,7 @@ def test_pdf_invoice(mock_payer, app, user):
|
|||
regie = Regie.objects.create(label='Foo')
|
||||
app.get('/api/regie/foo/invoice/%s/pdf/' % str(uuid.uuid4()), status=404)
|
||||
|
||||
resp = app.get(
|
||||
'/api/regie/foo/invoice/%s/pdf/' % str(uuid.uuid4()), params={'NameID': 'foobar'}, status=404
|
||||
)
|
||||
app.get('/api/regie/foo/invoice/%s/pdf/' % str(uuid.uuid4()), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
invoice = Invoice.objects.create(
|
||||
label='My invoice',
|
||||
|
@ -1360,9 +1358,7 @@ def test_pdf_invoice(mock_payer, app, user):
|
|||
# publication date is in the future
|
||||
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
||||
invoice.save()
|
||||
resp = app.get(
|
||||
'/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404
|
||||
)
|
||||
app.get('/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
# other regie
|
||||
other_regie = Regie.objects.create(label='Other Foo')
|
||||
|
@ -1422,7 +1418,7 @@ def test_pdf_invoice_for_payer(app, user):
|
|||
regie = Regie.objects.create(label='Foo')
|
||||
app.get('/api/regie/foo/invoice/%s/pdf/' % str(uuid.uuid4()), status=404)
|
||||
|
||||
resp = app.get(
|
||||
app.get(
|
||||
'/api/regie/foo/invoice/%s/pdf/' % str(uuid.uuid4()),
|
||||
params={'payer_external_id': 'payer:1'},
|
||||
status=404,
|
||||
|
@ -1525,7 +1521,7 @@ def test_pdf_invoice_payments(mock_payer, app, user):
|
|||
PaymentType.create_defaults(regie)
|
||||
app.get('/api/regie/foo/invoice/%s/payments/pdf/' % str(uuid.uuid4()), status=404)
|
||||
|
||||
resp = app.get(
|
||||
app.get(
|
||||
'/api/regie/foo/invoice/%s/payments/pdf/' % str(uuid.uuid4()), params={'NameID': 'foobar'}, status=404
|
||||
)
|
||||
|
||||
|
@ -1568,7 +1564,7 @@ def test_pdf_invoice_payments(mock_payer, app, user):
|
|||
# publication date is in the future
|
||||
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
||||
invoice.save()
|
||||
resp = app.get(
|
||||
app.get(
|
||||
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404
|
||||
)
|
||||
|
||||
|
@ -1658,7 +1654,7 @@ def test_pdf_invoice_payments_for_payer(app, user):
|
|||
PaymentType.create_defaults(regie)
|
||||
app.get('/api/regie/foo/invoice/%s/payments/pdf/' % str(uuid.uuid4()), status=404)
|
||||
|
||||
resp = app.get(
|
||||
app.get(
|
||||
'/api/regie/foo/invoice/%s/payments/pdf/' % str(uuid.uuid4()),
|
||||
params={'payer_external_id': 'payer:1'},
|
||||
status=404,
|
||||
|
@ -1809,12 +1805,12 @@ def test_pay_invoice(app, user):
|
|||
invoice.refresh_from_db()
|
||||
|
||||
# no payment type 'online'
|
||||
resp = app.post('/api/regie/foo/invoice/%s/pay/' % str(invoice.uuid), status=404)
|
||||
app.post('/api/regie/foo/invoice/%s/pay/' % str(invoice.uuid), status=404)
|
||||
|
||||
# no payment type 'online' for the regie
|
||||
other_regie = Regie.objects.create(label='Bar')
|
||||
PaymentType.create_defaults(other_regie)
|
||||
resp = app.post('/api/regie/foo/invoice/%s/pay/' % str(invoice.uuid), status=404)
|
||||
app.post('/api/regie/foo/invoice/%s/pay/' % str(invoice.uuid), status=404)
|
||||
|
||||
PaymentType.create_defaults(regie) # create default payment types
|
||||
resp = app.post('/api/regie/foo/invoice/%s/pay/' % str(invoice.uuid))
|
||||
|
@ -2199,6 +2195,7 @@ def test_close_draft_invoice(app, user):
|
|||
|
||||
resp = app.post('/api/regie/foo/draft-invoice/%s/close/' % str(invoice.uuid))
|
||||
assert resp.json['err'] == 0
|
||||
assert Credit.objects.count() == 0
|
||||
final_invoice = Invoice.objects.latest('pk')
|
||||
today = datetime.date.today()
|
||||
assert resp.json['data'] == {'invoice_id': str(final_invoice.uuid)}
|
||||
|
@ -2256,12 +2253,63 @@ def test_close_draft_invoice(app, user):
|
|||
invoice.save()
|
||||
app.post('/api/regie/foo/draft-invoice/%s/close/' % str(invoice.uuid), status=404)
|
||||
|
||||
invoice.pool = None
|
||||
invoice.save()
|
||||
line2 = DraftInvoiceLine.objects.create(
|
||||
event_date=datetime.date(2023, 4, 21),
|
||||
quantity=-1,
|
||||
unit_amount=45,
|
||||
invoice=invoice,
|
||||
)
|
||||
line2.refresh_from_db()
|
||||
invoice.refresh_from_db()
|
||||
final_line.delete()
|
||||
final_invoice.delete()
|
||||
resp = app.post('/api/regie/foo/draft-invoice/%s/close/' % str(invoice.uuid))
|
||||
assert resp.json['err'] == 0
|
||||
assert Invoice.objects.count() == 0
|
||||
credit = Credit.objects.latest('pk')
|
||||
assert resp.json['data'] == {'credit_id': str(credit.uuid)}
|
||||
assert credit.regie == regie
|
||||
assert credit.payer_external_id == invoice.payer_external_id
|
||||
assert credit.payer_first_name == invoice.payer_first_name
|
||||
assert credit.payer_last_name == invoice.payer_last_name
|
||||
assert credit.payer_address == invoice.payer_address
|
||||
assert credit.total_amount == -invoice.total_amount == 3
|
||||
assert credit.number == 1
|
||||
assert credit.formatted_number == 'A%02d-%s-0000001' % (regie.pk, today.strftime('%y-%m'))
|
||||
assert credit.pool is None
|
||||
assert credit.date_publication == datetime.date(2023, 4, 21)
|
||||
|
||||
credit_line1 = CreditLine.objects.order_by('pk')[0]
|
||||
assert credit_line1.event_date == line.event_date
|
||||
assert credit_line1.slug == line.slug
|
||||
assert credit_line1.label == line.label
|
||||
assert credit_line1.quantity == -line.quantity
|
||||
assert credit_line1.unit_amount == line.unit_amount
|
||||
assert credit_line1.total_amount == -line.total_amount
|
||||
assert credit_line1.user_external_id == line.user_external_id
|
||||
assert credit_line1.user_first_name == line.user_first_name
|
||||
assert credit_line1.user_last_name == line.user_last_name
|
||||
assert credit_line1.credit == credit
|
||||
credit_line2 = CreditLine.objects.order_by('pk')[1]
|
||||
assert credit_line2.event_date == line2.event_date
|
||||
assert credit_line2.slug == line2.slug
|
||||
assert credit_line2.label == line2.label
|
||||
assert credit_line2.quantity == -line2.quantity
|
||||
assert credit_line2.unit_amount == line2.unit_amount
|
||||
assert credit_line2.total_amount == -line2.total_amount
|
||||
assert credit_line2.user_external_id == line2.user_external_id
|
||||
assert credit_line2.user_first_name == line2.user_first_name
|
||||
assert credit_line2.user_last_name == line2.user_last_name
|
||||
assert credit_line2.credit == credit
|
||||
|
||||
|
||||
def test_add_injected_line(app, user):
|
||||
app.post('/api/regie/foo/injected-lines/', status=403)
|
||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||
|
||||
resp = app.post('/api/regie/foo/injected-lines/', status=404)
|
||||
app.post('/api/regie/foo/injected-lines/', status=404)
|
||||
|
||||
regie = Regie.objects.create(slug='foo')
|
||||
resp = app.post('/api/regie/foo/injected-lines/', status=400)
|
||||
|
@ -2315,7 +2363,7 @@ def test_add_payment(app, user):
|
|||
app.post('/api/regie/foo/payments/', status=403)
|
||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||
|
||||
resp = app.post('/api/regie/foo/payments/', status=404)
|
||||
app.post('/api/regie/foo/payments/', status=404)
|
||||
|
||||
regie = Regie.objects.create(slug='foo')
|
||||
resp = app.post('/api/regie/foo/payments/', status=400)
|
||||
|
@ -3015,9 +3063,7 @@ def test_pdf_payment(mock_payer, app, user):
|
|||
PaymentType.create_defaults(regie)
|
||||
app.get('/api/regie/foo/payment/%s/pdf/' % str(uuid.uuid4()), status=404)
|
||||
|
||||
resp = app.get(
|
||||
'/api/regie/foo/payment/%s/pdf/' % str(uuid.uuid4()), params={'NameID': 'foobar'}, status=404
|
||||
)
|
||||
app.get('/api/regie/foo/payment/%s/pdf/' % str(uuid.uuid4()), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
invoice = Invoice.objects.create(
|
||||
label='My invoice',
|
||||
|
@ -3056,13 +3102,11 @@ def test_pdf_payment(mock_payer, app, user):
|
|||
other_regie = Regie.objects.create(label='Other Foo')
|
||||
payment.regie = other_regie
|
||||
payment.save()
|
||||
resp = app.get(
|
||||
'/api/regie/foo/payment/%s/pdf/' % str(payment.uuid), params={'NameID': 'foobar'}, status=404
|
||||
)
|
||||
app.get('/api/regie/foo/payment/%s/pdf/' % str(payment.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
# no matching payer id
|
||||
mock_payer.return_value = 'payer:unknown'
|
||||
resp = app.get('/api/regie/foo/payment/%s/' % str(payment.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
app.get('/api/regie/foo/payment/%s/' % str(payment.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
# payer error
|
||||
mock_payer.side_effect = PayerError
|
||||
|
@ -3079,7 +3123,7 @@ def test_pdf_payment_for_payer(app, user):
|
|||
PaymentType.create_defaults(regie)
|
||||
app.get('/api/regie/foo/payment/%s/pdf/' % str(uuid.uuid4()), status=404)
|
||||
|
||||
resp = app.get(
|
||||
app.get(
|
||||
'/api/regie/foo/payment/%s/pdf/' % str(uuid.uuid4()),
|
||||
params={'payer_external_id': 'payer:1'},
|
||||
status=404,
|
||||
|
@ -3123,7 +3167,7 @@ def test_pdf_payment_for_payer(app, user):
|
|||
other_regie = Regie.objects.create(label='Other Foo')
|
||||
payment.regie = other_regie
|
||||
payment.save()
|
||||
resp = app.get(
|
||||
app.get(
|
||||
'/api/regie/foo/payment/%s/pdf/' % str(payment.uuid),
|
||||
params={'payer_external_id': 'payer:1'},
|
||||
status=404,
|
||||
|
@ -3159,6 +3203,7 @@ def test_list_credits(mock_payer, app, user):
|
|||
payment.save()
|
||||
credit = Credit.objects.create(
|
||||
label='Credit from 01/09/2022',
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
payer_first_name='First1',
|
||||
|
@ -3209,17 +3254,60 @@ def test_list_credits(mock_payer, app, user):
|
|||
]
|
||||
assert mock_payer.call_args_list == [mock.call(regie, mock.ANY, 'foobar')]
|
||||
|
||||
# publication date is in the future
|
||||
credit.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/', params={'NameID': 'foobar'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# credit is cancelled
|
||||
credit.date_publication = datetime.date(2022, 10, 1)
|
||||
credit.cancelled_at = now()
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/', params={'NameID': 'foobar'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# other regie
|
||||
other_regie = Regie.objects.create(label='Other Foo')
|
||||
credit.cancelled_at = None
|
||||
credit.regie = other_regie
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/', params={'NameID': 'foobar'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# no matching payer id
|
||||
# campaign is not finalized
|
||||
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_due=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
finalized=False,
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
)
|
||||
credit.regie = regie
|
||||
credit.pool = pool
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/', params={'NameID': 'foobar'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# campaign is finalized
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
resp = app.get('/api/regie/foo/credits/', params={'NameID': 'foobar'})
|
||||
assert resp.json['err'] == 0
|
||||
assert len(resp.json['data']) == 1
|
||||
|
||||
# no matching payer id
|
||||
mock_payer.return_value = 'payer:unknown'
|
||||
resp = app.get('/api/regie/foo/credits/', params={'NameID': 'foobar'})
|
||||
assert resp.json['err'] == 0
|
||||
|
@ -3275,6 +3363,7 @@ def test_list_credits_for_payer(app, user):
|
|||
payment.save()
|
||||
credit = Credit.objects.create(
|
||||
label='Credit from 01/09/2022',
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
payer_first_name='First1',
|
||||
|
@ -3323,17 +3412,60 @@ def test_list_credits_for_payer(app, user):
|
|||
}
|
||||
]
|
||||
|
||||
# publication date is in the future
|
||||
credit.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/', params={'payer_external_id': 'payer:1'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# credit is cancelled
|
||||
credit.date_publication = datetime.date(2022, 10, 1)
|
||||
credit.cancelled_at = now()
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/', params={'payer_external_id': 'payer:1'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# other regie
|
||||
other_regie = Regie.objects.create(label='Other Foo')
|
||||
credit.cancelled_at = None
|
||||
credit.regie = other_regie
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/', params={'payer_external_id': 'payer:1'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# credit fully assigned
|
||||
# campaign is not finalized
|
||||
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_due=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
finalized=False,
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
)
|
||||
credit.regie = regie
|
||||
credit.pool = pool
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/', params={'payer_external_id': 'payer:1'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# campaign is finalized
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
resp = app.get('/api/regie/foo/credits/', params={'payer_external_id': 'payer:1'})
|
||||
assert resp.json['err'] == 0
|
||||
assert len(resp.json['data']) == 1
|
||||
|
||||
# credit fully assigned
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment,
|
||||
|
@ -3374,6 +3506,7 @@ def test_list_history_credits(mock_payer, app, user):
|
|||
payment.save()
|
||||
credit = Credit.objects.create(
|
||||
label='Credit from 01/09/2022',
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
payer_first_name='First1',
|
||||
|
@ -3413,6 +3546,7 @@ def test_list_history_credits(mock_payer, app, user):
|
|||
credit=credit,
|
||||
amount=41,
|
||||
)
|
||||
credit.refresh_from_db()
|
||||
resp = app.get('/api/regie/foo/credits/history/', params={'NameID': 'foobar'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == [
|
||||
|
@ -3436,17 +3570,60 @@ def test_list_history_credits(mock_payer, app, user):
|
|||
]
|
||||
assert mock_payer.call_args_list == [mock.call(regie, mock.ANY, 'foobar')]
|
||||
|
||||
# publication date is in the future
|
||||
credit.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/history/', params={'NameID': 'foobar'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# credit is cancelled
|
||||
credit.date_publication = datetime.date(2022, 10, 1)
|
||||
credit.cancelled_at = now()
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/history/', params={'NameID': 'foobar'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# other regie
|
||||
other_regie = Regie.objects.create(label='Other Foo')
|
||||
credit.cancelled_at = None
|
||||
credit.regie = other_regie
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/history/', params={'NameID': 'foobar'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# no matching payer id
|
||||
# campaign is not finalized
|
||||
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_due=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
finalized=False,
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
)
|
||||
credit.regie = regie
|
||||
credit.pool = pool
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/history/', params={'NameID': 'foobar'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# campaign is finalized
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
resp = app.get('/api/regie/foo/credits/history/', params={'NameID': 'foobar'})
|
||||
assert resp.json['err'] == 0
|
||||
assert len(resp.json['data']) == 1
|
||||
|
||||
# no matching payer id
|
||||
mock_payer.return_value = 'payer:unknown'
|
||||
resp = app.get('/api/regie/foo/credits/history/', params={'NameID': 'foobar'})
|
||||
assert resp.json['err'] == 0
|
||||
|
@ -3454,7 +3631,7 @@ def test_list_history_credits(mock_payer, app, user):
|
|||
|
||||
# payer error
|
||||
mock_payer.side_effect = PayerError
|
||||
app.get('/api/regie/foo/credits/', params={'NameID': 'foobar'}, status=404)
|
||||
app.get('/api/regie/foo/credits/history/', params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
|
||||
def test_list_history_credits_for_payer(app, user):
|
||||
|
@ -3489,6 +3666,7 @@ def test_list_history_credits_for_payer(app, user):
|
|||
payment.save()
|
||||
credit = Credit.objects.create(
|
||||
label='Credit from 01/09/2022',
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
payer_first_name='First1',
|
||||
|
@ -3526,6 +3704,7 @@ def test_list_history_credits_for_payer(app, user):
|
|||
credit=credit,
|
||||
amount=41,
|
||||
)
|
||||
credit.refresh_from_db()
|
||||
resp = app.get('/api/regie/foo/credits/history/', params={'payer_external_id': 'payer:1'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == [
|
||||
|
@ -3548,14 +3727,59 @@ def test_list_history_credits_for_payer(app, user):
|
|||
}
|
||||
]
|
||||
|
||||
# publication date is in the future
|
||||
credit.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/history/', params={'payer_external_id': 'payer:1'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# credit is cancelled
|
||||
credit.date_publication = datetime.date(2022, 10, 1)
|
||||
credit.cancelled_at = now()
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/history/', params={'payer_external_id': 'payer:1'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# other regie
|
||||
other_regie = Regie.objects.create(label='Other Foo')
|
||||
credit.cancelled_at = None
|
||||
credit.regie = other_regie
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/history/', params={'payer_external_id': 'payer:1'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# campaign is not finalized
|
||||
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_due=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
finalized=False,
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
)
|
||||
credit.regie = regie
|
||||
credit.pool = pool
|
||||
credit.save()
|
||||
resp = app.get('/api/regie/foo/credits/history/', params={'payer_external_id': 'payer:1'})
|
||||
assert resp.json['err'] == 0
|
||||
assert resp.json['data'] == []
|
||||
|
||||
# campaign is finalized
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
resp = app.get('/api/regie/foo/credits/history/', params={'payer_external_id': 'payer:1'})
|
||||
assert resp.json['err'] == 0
|
||||
assert len(resp.json['data']) == 1
|
||||
|
||||
|
||||
@mock.patch.object(Regie, 'get_payer_external_id_from_nameid', autospec=True)
|
||||
def test_pdf_credit(mock_payer, app, user):
|
||||
|
@ -3568,12 +3792,11 @@ def test_pdf_credit(mock_payer, app, user):
|
|||
PaymentType.create_defaults(regie)
|
||||
app.get('/api/regie/foo/credit/%s/pdf/' % str(uuid.uuid4()), status=404)
|
||||
|
||||
resp = app.get(
|
||||
'/api/regie/foo/credit/%s/pdf/' % str(uuid.uuid4()), params={'NameID': 'foobar'}, status=404
|
||||
)
|
||||
app.get('/api/regie/foo/credit/%s/pdf/' % str(uuid.uuid4()), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
credit = Credit.objects.create(
|
||||
label='Credit from 01/09/2022',
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
payer_first_name='First1',
|
||||
|
@ -3585,17 +3808,55 @@ def test_pdf_credit(mock_payer, app, user):
|
|||
resp = app.get('/api/regie/foo/credit/%s/pdf/' % str(credit.uuid), params={'NameID': 'foobar'})
|
||||
assert resp.headers['Content-Disposition'] == 'attachment; filename="%s.pdf"' % credit.formatted_number
|
||||
|
||||
# publication date is in the future
|
||||
credit.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
||||
credit.save()
|
||||
app.get('/api/regie/foo/credit/%s/pdf/' % str(credit.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
# credit is cancelled
|
||||
credit.date_publication = datetime.date(2022, 10, 1)
|
||||
credit.cancelled_at = now()
|
||||
credit.save()
|
||||
app.get('/api/regie/foo/credit/%s/pdf/' % str(credit.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
# other regie
|
||||
other_regie = Regie.objects.create(label='Other Foo')
|
||||
credit.cancelled_at = None
|
||||
credit.regie = other_regie
|
||||
credit.save()
|
||||
resp = app.get(
|
||||
'/api/regie/foo/credit/%s/pdf/' % str(credit.uuid), params={'NameID': 'foobar'}, status=404
|
||||
app.get('/api/regie/foo/credit/%s/pdf/' % str(credit.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
# campaign is not finalized
|
||||
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_due=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
finalized=False,
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
)
|
||||
credit.regie = regie
|
||||
credit.pool = pool
|
||||
credit.save()
|
||||
app.get('/api/regie/foo/credit/%s/pdf/' % str(credit.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
# campaign is finalized
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
app.get(
|
||||
'/api/regie/foo/credit/%s/pdf/' % str(credit.uuid),
|
||||
params={'NameID': 'foobar'},
|
||||
)
|
||||
|
||||
# no matching payer id
|
||||
mock_payer.return_value = 'payer:unknown'
|
||||
resp = app.get('/api/regie/foo/credit/%s/' % str(credit.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
app.get('/api/regie/foo/credit/%s/' % str(credit.uuid), params={'NameID': 'foobar'}, status=404)
|
||||
|
||||
# payer error
|
||||
mock_payer.side_effect = PayerError
|
||||
|
@ -3612,7 +3873,7 @@ def test_pdf_credit_for_payer(app, user):
|
|||
PaymentType.create_defaults(regie)
|
||||
app.get('/api/regie/foo/credit/%s/pdf/' % str(uuid.uuid4()), status=404)
|
||||
|
||||
resp = app.get(
|
||||
app.get(
|
||||
'/api/regie/foo/credit/%s/pdf/' % str(uuid.uuid4()),
|
||||
params={'payer_external_id': 'payer:1'},
|
||||
status=404,
|
||||
|
@ -3620,6 +3881,7 @@ def test_pdf_credit_for_payer(app, user):
|
|||
|
||||
credit = Credit.objects.create(
|
||||
label='Credit from 01/09/2022',
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
payer_first_name='First1',
|
||||
|
@ -3636,18 +3898,74 @@ def test_pdf_credit_for_payer(app, user):
|
|||
other_regie = Regie.objects.create(label='Other Foo')
|
||||
credit.regie = other_regie
|
||||
credit.save()
|
||||
resp = app.get(
|
||||
# publication date is in the future
|
||||
credit.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
||||
credit.save()
|
||||
app.get(
|
||||
'/api/regie/foo/credit/%s/pdf/' % str(credit.uuid),
|
||||
params={'payer_external_id': 'payer:1'},
|
||||
status=404,
|
||||
)
|
||||
|
||||
# credit is cancelled
|
||||
credit.date_publication = datetime.date(2022, 10, 1)
|
||||
credit.cancelled_at = now()
|
||||
credit.save()
|
||||
app.get(
|
||||
'/api/regie/foo/credit/%s/pdf/' % str(credit.uuid),
|
||||
params={'payer_external_id': 'payer:1'},
|
||||
status=404,
|
||||
)
|
||||
|
||||
# other regie
|
||||
other_regie = Regie.objects.create(label='Other Foo')
|
||||
credit.cancelled_at = None
|
||||
credit.regie = other_regie
|
||||
credit.save()
|
||||
app.get(
|
||||
'/api/regie/foo/credit/%s/pdf/' % str(credit.uuid),
|
||||
params={'payer_external_id': 'payer:1'},
|
||||
status=404,
|
||||
)
|
||||
|
||||
# campaign is not finalized
|
||||
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_due=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
finalized=False,
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
)
|
||||
credit.regie = regie
|
||||
credit.pool = pool
|
||||
credit.save()
|
||||
app.get(
|
||||
'/api/regie/foo/credit/%s/pdf/' % str(credit.uuid),
|
||||
params={'payer_external_id': 'payer:1'},
|
||||
status=404,
|
||||
)
|
||||
|
||||
# campaign is finalized
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
app.get(
|
||||
'/api/regie/foo/credit/%s/pdf/' % str(credit.uuid),
|
||||
params={'payer_external_id': 'payer:1'},
|
||||
)
|
||||
|
||||
|
||||
def test_add_refund(app, user):
|
||||
app.post('/api/regie/foo/refunds/', status=403)
|
||||
app.authorization = ('Basic', ('john.doe', 'password'))
|
||||
|
||||
resp = app.post('/api/regie/foo/refunds/', status=404)
|
||||
app.post('/api/regie/foo/refunds/', status=404)
|
||||
|
||||
regie = Regie.objects.create(slug='foo')
|
||||
other_regie = Regie.objects.create(slug='bar')
|
||||
|
@ -3666,6 +3984,7 @@ def test_add_refund(app, user):
|
|||
|
||||
credit = Credit.objects.create(
|
||||
label='Credit from 01/09/2022',
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
payer_first_name='First1',
|
||||
|
@ -3684,17 +4003,92 @@ def test_add_refund(app, user):
|
|||
user_first_name='User1',
|
||||
user_last_name='Name1',
|
||||
)
|
||||
|
||||
# not the same regie
|
||||
other_credit = Credit.objects.create(
|
||||
label='Credit from 01/09/2022',
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=other_regie,
|
||||
payer_external_id='payer:1',
|
||||
payer_first_name='First1',
|
||||
payer_last_name='Name1',
|
||||
payer_address='41 rue des kangourous\n99999 Kangourou Ville',
|
||||
)
|
||||
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
params = {
|
||||
'credit': str(other_credit.uuid), # not the same regie
|
||||
'credit': str(other_credit.uuid),
|
||||
}
|
||||
resp = app.post('/api/regie/foo/refunds/', params=params, status=400)
|
||||
assert resp.json['err']
|
||||
assert resp.json['errors'] == {'credit': ['Unknown credit.']}
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date.today() + datetime.timedelta(days=1), # not publicated
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
params = {
|
||||
'credit': str(other_credit.uuid),
|
||||
}
|
||||
resp = app.post('/api/regie/foo/refunds/', params=params, status=400)
|
||||
assert resp.json['err']
|
||||
assert resp.json['errors'] == {'credit': ['Unknown credit.']}
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
cancelled_at=now(), # cancelled
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
params = {
|
||||
'credit': str(other_credit.uuid),
|
||||
}
|
||||
resp = app.post('/api/regie/foo/refunds/', params=params, status=400)
|
||||
assert resp.json['err']
|
||||
assert resp.json['errors'] == {'credit': ['Unknown credit.']}
|
||||
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_due=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
finalized=False,
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
)
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
pool=pool, # not finalized pool
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
params = {
|
||||
'credit': str(other_credit.uuid),
|
||||
}
|
||||
resp = app.post('/api/regie/foo/refunds/', params=params, status=400)
|
||||
assert resp.json['err']
|
||||
|
@ -3745,6 +4139,10 @@ def test_add_refund(app, user):
|
|||
user_last_name='Name1',
|
||||
)
|
||||
credit.refresh_from_db()
|
||||
campaign.finalized = True
|
||||
campaign.save()
|
||||
credit.pool = pool
|
||||
credit.save()
|
||||
assert credit.total_amount == 55
|
||||
assert credit.assigned_amount == 42
|
||||
assert credit.remaining_amount == 13
|
||||
|
|
|
@ -10,6 +10,7 @@ from pyquery import PyQuery
|
|||
|
||||
from lingo.basket.models import Basket, BasketLine, BasketLineItem
|
||||
from lingo.invoicing.models import (
|
||||
Campaign,
|
||||
Credit,
|
||||
CreditAssignment,
|
||||
CreditLine,
|
||||
|
@ -20,6 +21,7 @@ from lingo.invoicing.models import (
|
|||
InvoiceLinePayment,
|
||||
Payment,
|
||||
PaymentType,
|
||||
Pool,
|
||||
Regie,
|
||||
)
|
||||
from tests.utils import login
|
||||
|
@ -169,6 +171,7 @@ def test_basket_detail(app, simple_user):
|
|||
|
||||
# with available credit
|
||||
credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
|
@ -317,6 +320,7 @@ def test_basket_invoice_pdf(app, simple_user):
|
|||
basket.status = 'tobepaid'
|
||||
basket.save()
|
||||
credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
|
@ -489,6 +493,7 @@ def test_basket_validate_generate_invoice(app, simple_user):
|
|||
|
||||
# with credits, generated invoice is partially paid with credit
|
||||
credit1 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
|
@ -498,9 +503,25 @@ def test_basket_validate_generate_invoice(app, simple_user):
|
|||
quantity=1,
|
||||
unit_amount=1,
|
||||
)
|
||||
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_due=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
finalized=True,
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
)
|
||||
credit2 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
pool=pool,
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=credit2,
|
||||
|
@ -508,26 +529,77 @@ def test_basket_validate_generate_invoice(app, simple_user):
|
|||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
other_credit1 = Credit.objects.create(
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:2',
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit1,
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=1,
|
||||
unit_amount=1,
|
||||
)
|
||||
other_credit2 = Credit.objects.create(
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=other_regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit2,
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=1,
|
||||
unit_amount=1,
|
||||
)
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date.today() + datetime.timedelta(days=1), # not publicated
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
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_due=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
finalized=False,
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
)
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
pool=pool, # not finalized pool
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
cancelled_at=now(), # cancelled
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
basket.status = 'open'
|
||||
basket.save()
|
||||
resp = app.get('/basket/validate/')
|
||||
|
@ -631,6 +703,7 @@ def test_basket_validate_generate_invoice_nothing_to_pay(app, simple_user):
|
|||
line.payment_callback_url = 'http://payment1.com'
|
||||
line.save()
|
||||
credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
|
@ -730,6 +803,7 @@ def test_basket_validate_generate_credit(app, simple_user):
|
|||
|
||||
# credit is not used if basket amount is negative
|
||||
credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
|
@ -760,6 +834,8 @@ def test_basket_validate_generate_credit(app, simple_user):
|
|||
assert credit.payer_last_name == 'Last'
|
||||
assert credit.payer_address == '41 rue des kangourous\n99999 Kangourou Ville'
|
||||
assert credit.lines.count() == 1
|
||||
assert credit.pool is None
|
||||
assert credit.date_publication == datetime.date(2023, 4, 21)
|
||||
(line1,) = credit.lines.all().order_by('pk')
|
||||
assert line1.event_date == datetime.date(2022, 9, 1)
|
||||
assert line1.slug == 'event-a-foo-bar'
|
||||
|
@ -848,6 +924,7 @@ def test_basket_cancel(app, simple_user):
|
|||
app.get('/basket/cancel/', status=404)
|
||||
# the invoice is partially paid with a credit
|
||||
credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
|
|
|
@ -6,6 +6,7 @@ from django.utils.timezone import now
|
|||
|
||||
from lingo.basket.models import Basket, BasketLine
|
||||
from lingo.invoicing.models import (
|
||||
Campaign,
|
||||
Credit,
|
||||
CreditAssignment,
|
||||
CreditLine,
|
||||
|
@ -13,6 +14,7 @@ from lingo.invoicing.models import (
|
|||
DraftInvoiceLine,
|
||||
Invoice,
|
||||
InvoiceLine,
|
||||
Pool,
|
||||
Regie,
|
||||
)
|
||||
|
||||
|
@ -55,6 +57,7 @@ def test_basket_expiration():
|
|||
)
|
||||
# the invoice is partially paid with a credit
|
||||
credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
|
@ -98,6 +101,7 @@ def test_basket_expiration():
|
|||
expiry_at=now() + datetime.timedelta(minutes=1),
|
||||
)
|
||||
credit2 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
|
@ -233,6 +237,7 @@ def test_basket_amounts_with_draft_invoice():
|
|||
|
||||
# empty credit
|
||||
credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
|
@ -255,6 +260,7 @@ def test_basket_amounts_with_draft_invoice():
|
|||
|
||||
# credit for other payer
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:2',
|
||||
)
|
||||
|
@ -272,6 +278,7 @@ def test_basket_amounts_with_draft_invoice():
|
|||
# credit for other regie
|
||||
other_regie = Regie.objects.create(label='Bar')
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=other_regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
|
@ -286,7 +293,94 @@ def test_basket_amounts_with_draft_invoice():
|
|||
assert basket.credit_amount == -1
|
||||
assert basket.remaining_amount == 9
|
||||
|
||||
# not publicated credit
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date.today() + datetime.timedelta(days=1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
basket.draft_invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == -1
|
||||
assert basket.remaining_amount == 9
|
||||
|
||||
# non finalized campaign
|
||||
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_due=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
finalized=False,
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
)
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
pool=pool,
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
basket.draft_invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == -1
|
||||
assert basket.remaining_amount == 9
|
||||
|
||||
# cancelled credit
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
cancelled_at=now(),
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
basket.draft_invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == -1
|
||||
assert basket.remaining_amount == 9
|
||||
|
||||
# credit == amount to pay
|
||||
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_due=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
finalized=True,
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
)
|
||||
credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
pool=pool,
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -392,6 +486,7 @@ def test_basket_amounts_with_invoice():
|
|||
|
||||
# empty credit
|
||||
credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
|
|
|
@ -9,6 +9,7 @@ from django.utils.timezone import now
|
|||
from lingo.basket.models import Basket, BasketLine, BasketLineItem
|
||||
from lingo.epayment.models import PaymentBackend, Transaction
|
||||
from lingo.invoicing.models import (
|
||||
Campaign,
|
||||
Credit,
|
||||
CreditAssignment,
|
||||
CreditLine,
|
||||
|
@ -16,6 +17,7 @@ from lingo.invoicing.models import (
|
|||
DraftInvoiceLine,
|
||||
Payment,
|
||||
PaymentType,
|
||||
Pool,
|
||||
Regie,
|
||||
)
|
||||
from tests.utils import login
|
||||
|
@ -288,6 +290,7 @@ def test_basket_payment_with_assigned_credits(app, simple_user):
|
|||
line.save()
|
||||
|
||||
credit1 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
|
@ -297,9 +300,25 @@ def test_basket_payment_with_assigned_credits(app, simple_user):
|
|||
quantity=1,
|
||||
unit_amount=1,
|
||||
)
|
||||
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_due=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
finalized=True,
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
)
|
||||
credit2 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
pool=pool,
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=credit2,
|
||||
|
@ -309,6 +328,7 @@ def test_basket_payment_with_assigned_credits(app, simple_user):
|
|||
)
|
||||
other_regie = Regie.objects.create(label='Foo')
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=other_regie, # other regie
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
|
@ -319,6 +339,7 @@ def test_basket_payment_with_assigned_credits(app, simple_user):
|
|||
unit_amount=1,
|
||||
)
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:2', # other payer
|
||||
)
|
||||
|
@ -328,6 +349,55 @@ def test_basket_payment_with_assigned_credits(app, simple_user):
|
|||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date.today() + datetime.timedelta(days=1), # not publicated
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
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_due=datetime.date(2022, 10, 31),
|
||||
date_debit=datetime.date(2022, 11, 15),
|
||||
finalized=False,
|
||||
)
|
||||
pool = Pool.objects.create(
|
||||
campaign=campaign,
|
||||
draft=False,
|
||||
)
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
pool=pool, # not finalized pool
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
other_credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
cancelled_at=now(), # cancelled
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
|
||||
resp = app.get('/basket/validate/')
|
||||
resp = resp.form.submit()
|
||||
|
|
|
@ -3,6 +3,7 @@ import datetime
|
|||
import pytest
|
||||
|
||||
from lingo.invoicing.models import (
|
||||
Credit,
|
||||
Invoice,
|
||||
InvoiceCancellationReason,
|
||||
Payment,
|
||||
|
@ -82,6 +83,18 @@ def test_delete_invoice_reason(app, admin_user):
|
|||
|
||||
invoice.delete()
|
||||
|
||||
credit = Credit.objects.create(
|
||||
regie=regie,
|
||||
date_publication=datetime.date(2023, 4, 21),
|
||||
cancellation_reason=invoice_reason,
|
||||
)
|
||||
|
||||
resp = app.get('/manage/invoicing/cancellation-reasons/')
|
||||
assert '/manage/invoicing/cancellation-reason/invoice/%s/delete/' % invoice_reason.pk not in resp
|
||||
app.get('/manage/invoicing/cancellation-reason/invoice/%s/delete/' % invoice_reason.pk, status=404)
|
||||
|
||||
credit.delete()
|
||||
|
||||
resp = app.get('/manage/invoicing/cancellation-reasons/')
|
||||
resp = resp.click(href='/manage/invoicing/cancellation-reason/invoice/%s/delete/' % invoice_reason.pk)
|
||||
resp = resp.form.submit()
|
||||
|
|
|
@ -13,6 +13,7 @@ from lingo.invoicing.models import (
|
|||
CreditAssignment,
|
||||
CreditLine,
|
||||
Invoice,
|
||||
InvoiceCancellationReason,
|
||||
Payment,
|
||||
PaymentType,
|
||||
Refund,
|
||||
|
@ -35,6 +36,7 @@ def test_regie_credits(app, admin_user):
|
|||
regie=regie,
|
||||
)
|
||||
credit1 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
payer_first_name='First1',
|
||||
|
@ -44,6 +46,7 @@ def test_regie_credits(app, admin_user):
|
|||
credit1.set_number()
|
||||
credit1.save()
|
||||
credit2 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:2',
|
||||
payer_first_name='First2',
|
||||
|
@ -53,6 +56,7 @@ def test_regie_credits(app, admin_user):
|
|||
credit2.set_number()
|
||||
credit2.save()
|
||||
credit3 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:3',
|
||||
payer_first_name='First3',
|
||||
|
@ -61,6 +65,20 @@ def test_regie_credits(app, admin_user):
|
|||
)
|
||||
credit3.set_number()
|
||||
credit3.save()
|
||||
credit4 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:3',
|
||||
payer_first_name='First3',
|
||||
payer_last_name='Name3',
|
||||
payer_address='43 rue des kangourous\n99999 Kangourou Ville',
|
||||
cancelled_at=now(),
|
||||
cancelled_by=admin_user,
|
||||
cancellation_reason=InvoiceCancellationReason.objects.create(label='Final pool deletion'),
|
||||
cancellation_description='foo bar\nblah',
|
||||
)
|
||||
credit4.set_number()
|
||||
credit4.save()
|
||||
|
||||
CreditLine.objects.create(
|
||||
slug='event-a-foo-bar',
|
||||
|
@ -175,6 +193,21 @@ def test_regie_credits(app, admin_user):
|
|||
assert credit3.remaining_amount == 1
|
||||
assert credit3.assigned_amount == 0
|
||||
|
||||
CreditLine.objects.create(
|
||||
slug='injected',
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
credit=credit4,
|
||||
quantity=1,
|
||||
unit_amount=1,
|
||||
label='Event A',
|
||||
user_external_id='user:1',
|
||||
user_first_name='User1',
|
||||
user_last_name='Name1',
|
||||
)
|
||||
credit4.refresh_from_db()
|
||||
assert credit4.remaining_amount == 1
|
||||
assert credit4.assigned_amount == 0
|
||||
|
||||
app = login(app)
|
||||
resp = app.get('/manage/invoicing/regie/%s/credits/' % regie.pk)
|
||||
assert resp.pyquery(
|
||||
|
@ -291,31 +324,58 @@ def test_regie_credits(app, admin_user):
|
|||
'Remaining amount to assign: 1.00€',
|
||||
]
|
||||
|
||||
assert resp.pyquery(
|
||||
'tr[data-invoicing-element-id="%s"]' % credit4.pk
|
||||
).text() == 'Cancelled Credit A%02d-%s-0000004 dated %s for First3 Name3, amount 1.00€ - download' % (
|
||||
regie.pk,
|
||||
credit4.created_at.strftime('%y-%m'),
|
||||
credit4.created_at.strftime('%d/%m/%Y'),
|
||||
)
|
||||
assert len(resp.pyquery('tr[data-invoicing-element-id="%s"] a' % credit4.pk)) == 2
|
||||
lines_url = resp.pyquery('tr[data-invoicing-element-id="%s"]' % credit4.pk).attr(
|
||||
'data-invoicing-element-lines-url'
|
||||
)
|
||||
assert lines_url == '/manage/invoicing/ajax/regie/%s/credit/%s/lines/' % (
|
||||
regie.pk,
|
||||
credit4.pk,
|
||||
)
|
||||
lines_resp = app.get(lines_url)
|
||||
assert len(lines_resp.pyquery('tr')) == 7
|
||||
assert [PyQuery(tr).text() for tr in lines_resp.pyquery('tr')] == [
|
||||
'User1 Name1',
|
||||
'Description\nAccounting code\nAmount\nQuantity\nSubtotal',
|
||||
'Event A\n1.00€\n1\n1.00€',
|
||||
'Cancelled on: %s' % credit4.cancelled_at.strftime('%d/%m/%Y %H:%M'),
|
||||
'Cancelled by: admin',
|
||||
'Reason: Final pool deletion',
|
||||
'Description: foo bar\nblah',
|
||||
]
|
||||
|
||||
# test filters
|
||||
today = now().date()
|
||||
tomorrow = today + datetime.timedelta(days=1)
|
||||
yesterday = today - datetime.timedelta(days=1)
|
||||
params = [
|
||||
({'number': credit1.formatted_number}, 1),
|
||||
({'number': credit1.created_at.strftime('%y-%m')}, 3),
|
||||
({'created_at_after': today.strftime('%Y-%m-%d')}, 3),
|
||||
({'number': credit1.created_at.strftime('%y-%m')}, 4),
|
||||
({'created_at_after': today.strftime('%Y-%m-%d')}, 4),
|
||||
({'created_at_after': tomorrow.strftime('%Y-%m-%d')}, 0),
|
||||
({'created_at_before': yesterday.strftime('%Y-%m-%d')}, 0),
|
||||
({'created_at_before': today.strftime('%Y-%m-%d')}, 3),
|
||||
({'created_at_before': today.strftime('%Y-%m-%d')}, 4),
|
||||
({'payment_number': payment1.formatted_number}, 1),
|
||||
({'payment_number': payment1.created_at.strftime('%y-%m')}, 1),
|
||||
({'payer_external_id': 'payer:1'}, 1),
|
||||
({'payer_external_id': 'payer:2'}, 1),
|
||||
({'payer_first_name': 'first'}, 3),
|
||||
({'payer_first_name': 'first'}, 4),
|
||||
({'payer_first_name': 'first1'}, 1),
|
||||
({'payer_last_name': 'name'}, 3),
|
||||
({'payer_last_name': 'name'}, 4),
|
||||
({'payer_last_name': 'name1'}, 1),
|
||||
({'user_external_id': 'user:1'}, 3),
|
||||
({'user_external_id': 'user:1'}, 4),
|
||||
({'user_external_id': 'user:2'}, 1),
|
||||
({'user_first_name': 'user'}, 3),
|
||||
({'user_first_name': 'user'}, 4),
|
||||
({'user_first_name': 'user2'}, 1),
|
||||
({'user_last_name': 'name'}, 3),
|
||||
({'user_last_name': 'name1'}, 3),
|
||||
({'user_last_name': 'name'}, 4),
|
||||
({'user_last_name': 'name1'}, 4),
|
||||
(
|
||||
{
|
||||
'total_amount_min': '1',
|
||||
|
@ -328,25 +388,25 @@ def test_regie_credits(app, admin_user):
|
|||
'total_amount_min': '1',
|
||||
'total_amount_min_lookup': 'gte',
|
||||
},
|
||||
3,
|
||||
4,
|
||||
),
|
||||
(
|
||||
{
|
||||
'total_amount_max': '6.2',
|
||||
'total_amount_max_lookup': 'lt',
|
||||
},
|
||||
2,
|
||||
3,
|
||||
),
|
||||
(
|
||||
{
|
||||
'total_amount_max': '6.2',
|
||||
'total_amount_max_lookup': 'lte',
|
||||
},
|
||||
3,
|
||||
4,
|
||||
),
|
||||
({'assigned': 'yes'}, 1),
|
||||
({'assigned': 'partially'}, 1),
|
||||
({'assigned': 'no'}, 1),
|
||||
({'assigned': 'no'}, 2),
|
||||
({'agenda': 'agenda-a'}, 2),
|
||||
({'agenda': 'agenda-b'}, 1),
|
||||
({'event': 'agenda-a@event-a'}, 1),
|
||||
|
@ -355,6 +415,8 @@ def test_regie_credits(app, admin_user):
|
|||
({'accounting_code': '42'}, 0),
|
||||
({'accounting_code': '424242'}, 2),
|
||||
({'accounting_code': '424243'}, 1),
|
||||
({'cancelled': 'yes'}, 1),
|
||||
({'cancelled': 'no'}, 3),
|
||||
]
|
||||
for param, result in params:
|
||||
resp = app.get(
|
||||
|
@ -368,6 +430,7 @@ def test_regie_credit_pdf(app, admin_user):
|
|||
regie = Regie.objects.create(label='Foo', invoice_main_colour='#9141ac')
|
||||
credit = Credit.objects.create(
|
||||
label='Credit from 01/09/2022',
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
payer_first_name='First1',
|
||||
|
@ -466,6 +529,7 @@ def test_regie_refunds(app, admin_user):
|
|||
regie=regie,
|
||||
)
|
||||
credit1 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
payer_first_name='First1',
|
||||
|
@ -475,6 +539,7 @@ def test_regie_refunds(app, admin_user):
|
|||
credit1.set_number()
|
||||
credit1.save()
|
||||
credit2 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:2',
|
||||
payer_first_name='First2',
|
||||
|
@ -484,6 +549,7 @@ def test_regie_refunds(app, admin_user):
|
|||
credit2.set_number()
|
||||
credit2.save()
|
||||
credit3 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:3',
|
||||
payer_first_name='First3',
|
||||
|
|
|
@ -650,6 +650,7 @@ def test_regie_payment_cancel(app, admin_user):
|
|||
)
|
||||
credit = Credit.objects.create(
|
||||
label='Credit from 01/09/2022',
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
payer_first_name='First1',
|
||||
|
|
|
@ -13,6 +13,8 @@ from lingo.invoicing import utils
|
|||
from lingo.invoicing.models import (
|
||||
Campaign,
|
||||
Counter,
|
||||
Credit,
|
||||
CreditLine,
|
||||
DraftInvoice,
|
||||
DraftInvoiceLine,
|
||||
DraftJournalLine,
|
||||
|
@ -3906,6 +3908,57 @@ def test_promote_pool():
|
|||
payer_direct_debit=False,
|
||||
)
|
||||
|
||||
invoice4 = DraftInvoice.objects.create(
|
||||
date_publication=campaign.date_publication,
|
||||
date_payment_deadline=campaign.date_payment_deadline,
|
||||
date_due=campaign.date_due,
|
||||
regie=regie,
|
||||
pool=pool,
|
||||
payer_external_id='payer:1',
|
||||
payer_first_name='First1',
|
||||
payer_last_name='Last1',
|
||||
payer_address='41 rue des kangourous\n99999 Kangourou Ville',
|
||||
payer_demat=True,
|
||||
payer_direct_debit=False,
|
||||
)
|
||||
iline41 = DraftInvoiceLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
slug='label-41',
|
||||
label='Label 41',
|
||||
quantity=1,
|
||||
unit_amount=-1,
|
||||
event_slug='label-41',
|
||||
user_external_id='user:1',
|
||||
user_first_name='User1',
|
||||
user_last_name='Name1',
|
||||
payer_external_id='payer:2',
|
||||
payer_first_name='First2',
|
||||
payer_last_name='Last2',
|
||||
payer_address='42 rue des kangourous\n99999 Kangourou Ville',
|
||||
payer_demat=False,
|
||||
payer_direct_debit=True,
|
||||
invoice=invoice4,
|
||||
pool=pool,
|
||||
)
|
||||
line41 = DraftJournalLine.objects.create(
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
slug='label-41',
|
||||
label='Label 41',
|
||||
amount=-1,
|
||||
user_external_id='user:1',
|
||||
user_first_name='User1',
|
||||
user_last_name='Name1',
|
||||
payer_external_id='payer:2',
|
||||
payer_first_name='First2',
|
||||
payer_last_name='Last2',
|
||||
payer_address='42 rue des kangourous\n99999 Kangourou Ville',
|
||||
payer_demat=False,
|
||||
payer_direct_debit=True,
|
||||
status='success',
|
||||
pool=pool,
|
||||
invoice_line=iline41,
|
||||
)
|
||||
|
||||
old_invoice = DraftInvoice.objects.create(
|
||||
date_publication=campaign.date_publication,
|
||||
date_payment_deadline=campaign.date_payment_deadline,
|
||||
|
@ -4056,8 +4109,10 @@ def test_promote_pool():
|
|||
iline12.refresh_from_db()
|
||||
iline21.refresh_from_db()
|
||||
iline22.refresh_from_db()
|
||||
iline41.refresh_from_db()
|
||||
invoice1.refresh_from_db()
|
||||
invoice2.refresh_from_db()
|
||||
invoice4.refresh_from_db()
|
||||
|
||||
# orphan invoice
|
||||
orphan_invoice = DraftInvoice.objects.create(
|
||||
|
@ -4111,11 +4166,13 @@ def test_promote_pool():
|
|||
assert Campaign.objects.count() == 2
|
||||
assert Pool.objects.count() == 3
|
||||
assert Pool.objects.filter(draft=False).count() == 0
|
||||
assert DraftInvoice.objects.count() == 6
|
||||
assert DraftInvoiceLine.objects.count() == 9
|
||||
assert DraftJournalLine.objects.count() == 11
|
||||
assert DraftInvoice.objects.count() == 7
|
||||
assert DraftInvoiceLine.objects.count() == 10
|
||||
assert DraftJournalLine.objects.count() == 12
|
||||
assert Invoice.objects.count() == 0
|
||||
assert InvoiceLine.objects.count() == 0
|
||||
assert Credit.objects.count() == 0
|
||||
assert CreditLine.objects.count() == 0
|
||||
assert JournalLine.objects.count() == 0
|
||||
assert InjectedLine.objects.count() == 4
|
||||
|
||||
|
@ -4125,14 +4182,17 @@ def test_promote_pool():
|
|||
assert Campaign.objects.count() == 2
|
||||
assert Pool.objects.count() == 4
|
||||
assert Pool.objects.filter(draft=False).count() == 1
|
||||
assert DraftInvoice.objects.count() == 6
|
||||
assert DraftInvoiceLine.objects.count() == 9
|
||||
assert DraftJournalLine.objects.count() == 11
|
||||
assert DraftInvoice.objects.count() == 7
|
||||
assert DraftInvoiceLine.objects.count() == 10
|
||||
assert DraftJournalLine.objects.count() == 12
|
||||
assert Invoice.objects.count() == 3
|
||||
assert InvoiceLine.objects.count() == 4
|
||||
assert JournalLine.objects.count() == 6
|
||||
assert Credit.objects.count() == 1
|
||||
assert CreditLine.objects.count() == 1
|
||||
assert JournalLine.objects.count() == 7
|
||||
assert InjectedLine.objects.count() == 4
|
||||
assert Counter.objects.get(regie=regie, name=today.strftime('%y')).value == 3
|
||||
assert Counter.objects.get(regie=regie, kind='invoice', name=today.strftime('%y')).value == 3
|
||||
assert Counter.objects.get(regie=regie, kind='credit', name=today.strftime('%y')).value == 1
|
||||
|
||||
test_counts()
|
||||
|
||||
|
@ -4353,7 +4413,54 @@ def test_promote_pool():
|
|||
assert final_line22.from_injected_line is None
|
||||
assert final_line22.invoice_line == final_iline22
|
||||
|
||||
final_orphan_line1 = JournalLine.objects.order_by('pk')[4]
|
||||
credit = Credit.objects.order_by('pk')[0]
|
||||
assert credit.date_publication == invoice4.date_publication
|
||||
assert credit.regie == regie
|
||||
assert credit.pool == final_pool
|
||||
assert credit.payer_external_id == invoice4.payer_external_id
|
||||
assert credit.payer_first_name == invoice4.payer_first_name
|
||||
assert credit.payer_last_name == invoice4.payer_last_name
|
||||
assert credit.total_amount == -invoice4.total_amount == 1
|
||||
assert credit.number == 1
|
||||
assert credit.formatted_number == 'A%02d-%s-0000001' % (regie.pk, today.strftime('%y-%m'))
|
||||
|
||||
credit_line41 = CreditLine.objects.order_by('pk')[0]
|
||||
assert credit_line41.event_date == iline41.event_date
|
||||
assert credit_line41.slug == iline41.slug
|
||||
assert credit_line41.label == iline41.label
|
||||
assert credit_line41.quantity == -iline41.quantity
|
||||
assert credit_line41.unit_amount == iline41.unit_amount
|
||||
assert credit_line41.total_amount == -iline41.total_amount
|
||||
assert credit_line41.user_external_id == iline41.user_external_id
|
||||
assert credit_line41.user_first_name == iline41.user_first_name
|
||||
assert credit_line41.user_last_name == iline41.user_last_name
|
||||
assert credit_line41.event_slug == iline41.event_slug
|
||||
assert credit_line41.event_label == iline41.event_label
|
||||
assert credit_line41.agenda_slug == iline41.agenda_slug
|
||||
assert credit_line41.activity_label == iline41.activity_label
|
||||
assert credit_line41.credit == credit
|
||||
final_line41 = JournalLine.objects.order_by('pk')[4]
|
||||
assert final_line41.event_date == line41.event_date
|
||||
assert final_line41.slug == line41.slug
|
||||
assert final_line41.label == line41.label
|
||||
assert final_line41.amount == line41.amount
|
||||
assert final_line41.user_external_id == line41.user_external_id
|
||||
assert final_line41.user_first_name == line41.user_first_name
|
||||
assert final_line41.user_last_name == line41.user_last_name
|
||||
assert final_line41.payer_external_id == line41.payer_external_id
|
||||
assert final_line41.payer_first_name == line41.payer_first_name
|
||||
assert final_line41.payer_last_name == line41.payer_last_name
|
||||
assert final_line41.payer_address == line41.payer_address
|
||||
assert final_line41.payer_demat == line41.payer_demat
|
||||
assert final_line41.payer_direct_debit == line41.payer_direct_debit
|
||||
assert final_line41.event == line41.event
|
||||
assert final_line41.pricing_data == line41.pricing_data
|
||||
assert final_line41.status == line41.status
|
||||
assert final_line41.pool == final_pool
|
||||
assert final_line41.from_injected_line is None
|
||||
assert final_line41.credit_line == credit_line41
|
||||
|
||||
final_orphan_line1 = JournalLine.objects.order_by('pk')[5]
|
||||
assert final_orphan_line1.event_date == orphan_line1.event_date
|
||||
assert final_orphan_line1.slug == orphan_line1.slug
|
||||
assert final_orphan_line1.label == orphan_line1.label
|
||||
|
@ -4374,7 +4481,7 @@ def test_promote_pool():
|
|||
assert final_orphan_line1.from_injected_line is None
|
||||
assert final_orphan_line1.invoice_line is None
|
||||
|
||||
final_orphan_line2 = JournalLine.objects.order_by('pk')[5]
|
||||
final_orphan_line2 = JournalLine.objects.order_by('pk')[6]
|
||||
assert final_orphan_line2.event_date == orphan_line2.event_date
|
||||
assert final_orphan_line2.slug == orphan_line2.slug
|
||||
assert final_orphan_line2.label == orphan_line2.label
|
||||
|
|
|
@ -528,7 +528,10 @@ def test_invoice_payments(orphan):
|
|||
|
||||
def test_creditline_total_amount():
|
||||
regie = Regie.objects.create()
|
||||
credit = Credit.objects.create(regie=regie)
|
||||
credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
)
|
||||
|
||||
# create line
|
||||
line = CreditLine.objects.create(
|
||||
|
@ -566,9 +569,15 @@ def test_creditline_total_amount():
|
|||
def test_credit_total_amount():
|
||||
regie = Regie.objects.create()
|
||||
|
||||
credit = Credit.objects.create(regie=regie)
|
||||
credit = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
)
|
||||
assert credit.total_amount == 0
|
||||
credit2 = Credit.objects.create(regie=regie)
|
||||
credit2 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
)
|
||||
assert credit2.total_amount == 0
|
||||
|
||||
line = CreditLine.objects.create(
|
||||
|
@ -664,14 +673,20 @@ def test_credit_assignments():
|
|||
regie = Regie.objects.create()
|
||||
PaymentType.create_defaults(regie)
|
||||
|
||||
credit1 = Credit.objects.create(regie=regie)
|
||||
credit1 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
event_date=datetime.date.today(),
|
||||
credit=credit1,
|
||||
quantity=1,
|
||||
unit_amount=42,
|
||||
)
|
||||
credit2 = Credit.objects.create(regie=regie)
|
||||
credit2 = Credit.objects.create(
|
||||
date_publication=datetime.date(2022, 10, 1),
|
||||
regie=regie,
|
||||
)
|
||||
line2 = CreditLine.objects.create(
|
||||
event_date=datetime.date.today(),
|
||||
credit=credit2,
|
||||
|
|
Loading…
Reference in New Issue