invoice

https://gitlab.com/kb/invoice

Icon

Invoice:

<i class="fa fa-gbp"></i>

Time Recording:

<i class="fa fa-clock-o"></i>

Plan

I am trying to use the VatCode model in the invoice app, but we have a problem with the Contact record in the crm. The job app uses settings.CONTACT_MODEL, and the crm app has it’s own Contact.

I think the proper solution is to move Contact from the crm app and put it into a contact app.

Move TimeRecord from invoice to crm.

Update the invoice routines so they can invoice a generic line type. One of these types would be TimeRecord.

Create a new account app. Move VatCode into this account app.

At a later date, move the code from invoice and pay into the account app.

Credit Note

To create a credit note, list invoices for a contact, click Create draft invoice (without time records), enter the date for the credit note. Click Add line, enter a negative quantity and a positive price.

Warning

It is not possible to mix invoice and credit lines on one document. If you want to credit a customer, then create a separate credit note.

Date

To create an invoice for a particular date (the slug is for the contact):

from datetime import date
from crm.models import Contact
from django.contrib.auth.models import User
from invoice.service import InvoiceCreate

invoice_date = date(2013, 12, 31)
slug = 'kb'
user_name = 'patrick.kimber'

invoice_create = InvoiceCreate()
contact = Contact.objects.get(slug=slug)
user = User.objects.get(username=user_name)
invoice_create.create(user, contact, invoice_date)

To create the invoice PDF, follow the PDF instructions below…

Export to R (Shiny)

Management command:

django-admin.py export_to_r

Note

The source code is at export_to_r

  • The export file is tab separated.

  • The net column is the total net value for the line.

  • The quantity column is the number of items supplied.

Tip

To get the price of a product, divide the net value by the quantity.

Outstanding

Tip

This code has been added to the invoice app at the following URL, /invoice/time/outstanding/

Who do I need to invoice (run from project folder using django-admin shell):

from invoice.models import TimeRecord
qs = TimeRecord.objects.filter(invoice_line__isnull=True, billable=True).order_by('ticket__contact__slug').distinct('ticket__contact__slug')
for t in qs: print(t.ticket.contact.slug)

How much time have I spent on a ticket:

# edit the ticket numbers in the source code
django-admin.py ticket_time_csv

PDF

To create the PDF for an invoice:

from invoice.models import Invoice
from invoice.service import InvoicePrint

invoice_number = 53

invoice = Invoice.objects.get(pk=invoice_number)
invoice.contact.name
invoice.pdf = None
InvoicePrint().create_pdf(invoice, header_image=None)

Templates and Mixins

Tip

All projects which use the invoice app should provide a detail URL named invoice.detail.

BatchInvoiceListView

from invoice.views import BatchInvoiceListMixin

class BatchInvoiceListView(
    LoginRequiredMixin,
    StaffuserRequiredMixin,
    BatchInvoiceListMixin,
    BaseMixin,
    ListView,
):
    template_name = "dash/batch_invoice_list.html"

Tip

You can use example_invoice/templates/example/batch_invoice_list.html as a starting point for your own template.

from .views import BatchInvoiceListView

url(
    regex=r"^batch/(?P<pk>\d+)/invoice/$",
    view=BatchInvoiceListView.as_view(),
    name="invoice.batch.invoice.list",
),
from invoice.tests.factories import BatchFactory

@pytest.mark.django_db
def test_batch_invoice_list(perm_check):
    batch = BatchFactory()
    url = reverse("invoice.batch.invoice.list", args=[batch.pk])
    perm_check.staff(url)

InvoiceDetailMixin

from braces.views import LoginRequiredMixin, StaffuserRequiredMixin
from django.views.generic import DetailView, TemplateView

from invoice.views import InvoiceDetailMixin

class InvoiceDetailView(
    LoginRequiredMixin,
    StaffuserRequiredMixin,
    InvoiceDetailMixin,
    BaseMixin,
    DetailView,
):
    template_name = "dash/invoice_detail.html"

Tip

The example_invoice/templates/example/invoice_detail.html example template shows an example of how to use the detail view:

{% include "invoice/_invoice_detail_header.html" %}
{% include "invoice/_invoice_detail.html" %}
{% include "invoice/_invoice_detail_lines.html" %}

Tip

Also see Magento App for the invoice detail include for the Magento app.

from .views import InvoiceDetailView

url(
    regex=r"^invoice/(?P<pk>\d+)/$",
    view=InvoiceDetailView.as_view(),
    name="invoice.detail",
),

test_view_perm.py:

from invoice.tests.factories import InvoiceFactory

@pytest.mark.django_db
def test_invoice_detail(perm_check):
    invoice = InvoiceFactory()
    url = reverse("invoice.detail", args=[invoice.pk])
    perm_check.staff(url)

InvoiceListMixin

from invoice.views import InvoiceListMixin

class InvoiceListView(
    LoginRequiredMixin,
    StaffuserRequiredMixin,
    InvoiceListMixin,
    BaseMixin,
    ListView,
):
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context.update({"show_download": True})
        return context
from .views import InvoiceListView

url(
    regex=r"^invoice/$", view=InvoiceListView.as_view(), name="invoice.list"
),
DJANGO_APPS = (
    "django.contrib.humanize",
@pytest.mark.django_db
def test_invoice_list(perm_check):
    url = reverse("invoice.list")
    perm_check.staff(url)

Ticket Time

This is a temporary management command which will download all the time records for a list of tickets.

To use this command, start by restoring a backup of the data for your site.

Then edit the source code for the management command:

~/repo/dev/app/invoice/invoice/management/commands/ticket_time_csv.py

Update the list of numbers to include the tickets you want in your CSV file:

tickets = (
  732,

Run the management command:

django-admin.py ticket_time_csv