Commit 11b6f23e authored by Patrick Kimber's avatar Patrick Kimber

Remove duplicate invoice issue lines

https://www.kbsoftware.co.uk/crm/ticket/4522/
parent 3d9910e2
Pipeline #81876647 passed with stage
in 5 minutes and 36 seconds
# Generated by Django 2.2.4 on 2019-09-12 16:24
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [("invoice", "0023_auto_20190910_1137")]
operations = [
migrations.AlterModelOptions(
name="invoiceissue",
options={
"ordering": ("-invoice__invoice_date", "-invoice__pk"),
"verbose_name": "Invoice Issue",
"verbose_name_plural": "Invoice Issues",
},
),
migrations.AlterModelOptions(
name="invoiceissueline",
options={
"ordering": (
"-invoice_issue__invoice__invoice_date",
"-invoice_issue__invoice__pk",
"-pk",
),
"verbose_name": "Invoice Issue Line",
"verbose_name_plural": "Invoice Issue Lines",
},
),
migrations.AlterField(
model_name="invoiceissue",
name="invoice",
field=models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
to="invoice.Invoice",
),
),
migrations.AlterUniqueTogether(
name="invoiceissue", unique_together=set()
),
migrations.RemoveField(model_name="invoiceissue", name="issue_date"),
]
......@@ -619,18 +619,20 @@ class InvoiceIssueManager(models.Manager):
.. note:: This method returns the line for the issue (not the issue).
"""
issue_date = timezone.now().date()
try:
invoice_issue = InvoiceIssue.objects.get(
invoice=invoice, issue_date=issue_date
)
except InvoiceIssue.DoesNotExist:
invoice_issue = InvoiceIssue(invoice=invoice, issue_date=issue_date)
invoice_issue = self.model.objects.get(invoice=invoice)
except self.model.DoesNotExist:
invoice_issue = self.model(invoice=invoice)
invoice_issue.save()
invoice_issue_line = InvoiceIssueLine(
invoice_issue=invoice_issue, description=description
)
invoice_issue_line.save()
try:
invoice_issue_line = InvoiceIssueLine.objects.get(
invoice_issue=invoice_issue, description=description
)
except InvoiceIssueLine.DoesNotExist:
invoice_issue_line = InvoiceIssueLine(
invoice_issue=invoice_issue, description=description
)
invoice_issue_line.save()
return invoice_issue_line
def issues(self, invoice_date=None):
......@@ -653,8 +655,7 @@ class InvoiceIssue(models.Model):
"""
invoice = models.ForeignKey(Invoice, on_delete=models.CASCADE)
issue_date = models.DateField()
invoice = models.OneToOneField(Invoice, on_delete=models.CASCADE)
confirmed = models.BooleanField(default=False)
confirmed_by_user = models.ForeignKey(
settings.AUTH_USER_MODEL,
......@@ -666,8 +667,7 @@ class InvoiceIssue(models.Model):
objects = InvoiceIssueManager()
class Meta:
ordering = ("-issue_date", "-invoice__pk")
unique_together = ("invoice", "issue_date")
ordering = ("-invoice__invoice_date", "-invoice__pk")
verbose_name = "Invoice Issue"
verbose_name_plural = "Invoice Issues"
......@@ -675,7 +675,7 @@ class InvoiceIssue(models.Model):
return "Invoice issue {} for {} dated {}".format(
self.pk,
self.invoice.invoice_number,
self.issue_date.strftime("%d/%m/%Y"),
self.invoice.invoice_date.strftime("%d/%m/%Y"),
)
def lines(self):
......@@ -688,7 +688,7 @@ class InvoiceIssueLine(TimeStampedModel):
class Meta:
ordering = (
"-invoice_issue__issue_date",
"-invoice_issue__invoice__invoice_date",
"-invoice_issue__invoice__pk",
"-pk",
)
......@@ -699,7 +699,7 @@ class InvoiceIssueLine(TimeStampedModel):
return "Invoice issue {} for {} dated {}: {}".format(
self.invoice_issue.pk,
self.invoice_issue.invoice.invoice_number,
self.invoice_issue.issue_date.strftime("%d/%m/%Y"),
self.created.strftime("%d/%m/%Y %H:%M"),
self.description,
)
......
......@@ -101,7 +101,6 @@ class InvoiceIssueFactory(factory.django.DjangoModelFactory):
model = InvoiceIssue
invoice = factory.SubFactory(InvoiceFactory)
issue_date = date.today()
class InvoiceLineFactory(factory.django.DjangoModelFactory):
......
# -*- encoding: utf-8 -*-
import pytest
import pytz
from datetime import date
from datetime import date, datetime
from django.db import IntegrityError
from freezegun import freeze_time
......@@ -18,7 +19,7 @@ def test_duplicate():
with freeze_time(date(2019, 7, 20)):
InvoiceIssue.objects.init_invoice_issue(invoice, "Apple")
with pytest.raises(IntegrityError) as e:
InvoiceIssueFactory(invoice=invoice, issue_date=date.today())
InvoiceIssueFactory(invoice=invoice)
assert "duplicate key value violates unique constraint" in str(e.value)
......@@ -51,6 +52,21 @@ def test_init_invoice_issue_two_issues_for_one_invoice():
assert 2 == InvoiceIssueLine.objects.count()
@pytest.mark.django_db
def test_init_invoice_issue_duplicate_date_and_description():
invoice = InvoiceFactory()
with freeze_time(date(2019, 1, 1)):
InvoiceIssue.objects.init_invoice_issue(invoice, "A")
with freeze_time(date(2019, 1, 31)):
InvoiceIssue.objects.init_invoice_issue(invoice, "A")
InvoiceIssue.objects.init_invoice_issue(invoice, "B")
InvoiceIssue.objects.init_invoice_issue(invoice, "C")
assert ["A", "B", "C"] == [
x.description
for x in InvoiceIssueLine.objects.all().order_by("description")
]
@pytest.mark.parametrize(
"invoice_date,expect",
[
......@@ -132,26 +148,26 @@ def test_lines():
@pytest.mark.django_db
def test_ordering():
invoice_1 = InvoiceFactory()
invoice_2 = InvoiceFactory()
invoice_1 = InvoiceFactory(invoice_date=date(2019, 1, 1))
invoice_2 = InvoiceFactory(invoice_date=date(2019, 1, 31))
with freeze_time(date(2019, 1, 1)):
issue_a = InvoiceIssue.objects.init_invoice_issue(invoice_2, "A")
issue_line_a = InvoiceIssue.objects.init_invoice_issue(invoice_1, "A")
with freeze_time(date(2019, 1, 31)):
issue_b = InvoiceIssue.objects.init_invoice_issue(invoice_1, "B")
assert [issue_b.invoice_issue.pk, issue_a.invoice_issue.pk] == [
issue_line_b = InvoiceIssue.objects.init_invoice_issue(invoice_2, "B")
assert [issue_line_b.invoice_issue.pk, issue_line_a.invoice_issue.pk] == [
x.pk for x in InvoiceIssue.objects.all()
]
@pytest.mark.django_db
def test_ordering_invoice_issue_line():
i1 = InvoiceFactory()
i2 = InvoiceFactory()
invoice_1 = InvoiceFactory(invoice_date=date(2019, 1, 31))
invoice_2 = InvoiceFactory(invoice_date=date(2019, 1, 1))
with freeze_time(date(2019, 1, 31)):
InvoiceIssue.objects.init_invoice_issue(i1, "x")
InvoiceIssue.objects.init_invoice_issue(i1, "z")
InvoiceIssue.objects.init_invoice_issue(invoice_1, "x")
InvoiceIssue.objects.init_invoice_issue(invoice_1, "z")
with freeze_time(date(2019, 1, 1)):
InvoiceIssue.objects.init_invoice_issue(i2, "y")
InvoiceIssue.objects.init_invoice_issue(invoice_2, "y")
assert ["z", "x", "y"] == [
x.description for x in InvoiceIssueLine.objects.all()
]
......@@ -160,22 +176,23 @@ def test_ordering_invoice_issue_line():
@pytest.mark.django_db
def test_str():
invoice_issue = InvoiceIssueFactory(
invoice=InvoiceFactory(number=3, prefix="I"),
issue_date=date(2019, 7, 31),
invoice=InvoiceFactory(
invoice_date=date(2019, 11, 23), number=3, prefix="I"
)
)
assert "Invoice issue {} for I000003 dated 31/07/2019".format(
assert "Invoice issue {} for I000003 dated 23/11/2019".format(
invoice_issue.pk
) == str(invoice_issue)
@pytest.mark.django_db
def test_str_invoice_issue_line():
with freeze_time(date(2019, 7, 31)):
with freeze_time(datetime(2019, 7, 31, 14, 23, 0, tzinfo=pytz.utc)):
InvoiceIssue.objects.init_invoice_issue(
InvoiceFactory(number=3, prefix="I"), "Lemon"
)
assert 1 == InvoiceIssueLine.objects.count()
invoice_issue_line = InvoiceIssueLine.objects.first()
assert "Invoice issue {} for I000003 dated 31/07/2019: Lemon".format(
assert "Invoice issue {} for I000003 dated 31/07/2019 14:23: Lemon".format(
invoice_issue_line.invoice_issue.pk
) == str(invoice_issue_line)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment