invoicing : Generating invoices

The lino_xl.lib.invoicing plugin adds functionality for invoicing, i.e. automatically generating invoices.

This document describes some general aspects of invoicing and how applications can handle this topic. More aspects in Invoicing in Lino Voga (lino_voga.lib.invoicing), Invoicing in Lino Voga (lino_voga.lib.invoicing) and How Lino Tera generates invoices.

You should have read invoicing: Generate invoices, sales : Product invoices and Accounting stuff in Lino.

This is a tested document. The following instructions are used for initialization:

>>> from lino import startup
>>> startup('lino_book.projects.roger.settings.demo')
>>> from lino.api.doctest import *
>>> ses = rt.login("robin")
>>> translation.activate('en')

API

This plugin requires the lino_xl.lib.sales plugin.

>>> dd.plugins.invoicing.needs_plugins
['lino_xl.lib.sales']

The plugin adds a main menu command Sales ‣ Generate invoices:

>>> show_menu_path(invoicing.PlansByArea.start_invoicing)
Sales --> Generate invoices

Invoice generators

In order to be able to automatically generate invoices (or similar trade documents), an application must have at least one model that acts as an invoice generator.

invoice generator

A database object that can potentially generate invoice items.

As an application developer you define an invoice generator by having a database model inherit from InvoiceGenerator. The following models inherit from InvoiceGenerator, and we recommend to look at their source code:

Reference

class lino_xl.lib.invoicing.InvoicingTargetVoucher

Mixin for Django models that can be used as invoicing.voucher_model.

class lino_xl.lib.invoicing.InvoicingTargetItem
invoiceable

A generic foreign key pointing to the generator that caused this item to be generated.

class lino_xl.lib.invoicing.InvoiceGenerator

Mixin for Django models that represent an invoice generator.

The application developer must implement a method get_invoiceable_events().

Methods and class attributes:

default_invoiceable_qty

The default value to return by get_invoiceable_qty().

get_invoice_items(self, info, invoice, ar)

Yield one or several invoice items generated by this object.

These must be instances of lino_xl.lib.sales.InvoiceItem.

get_invoiceable_events(self, start_date, max_date)

Return a Django query that represents the invoicing events.

The query must be sorted in the order they are to be considered for invoicing.

get_invoiceable_event_formatter(self)

Return a callable that formats an invoicing event as an HTML etree element.

get_generators_for_plan(cls, plan, partner=None)

Return a queryset of the database objects (of this model) that potentially will generate an invoice item.

This is a pre-selection, not every object must actually produce an invoice item.

If a partner is given, use it as an additional filter condition. Be aware that the partner here is the invoice recipient, not the invoiceable partner. So when filtering on the partner, this must add a "reverse mirroring" of the way we get the invoice recipient from the invoiceable partner. For example:

if partner:
    q1 = models.Q(
        pupil__salesrule__invoice_recipient__isnull=True, pupil=pupil)
    q2 = models.Q(pupil__salesrule__invoice_recipient=partner)
    qs = qs.filter(models.Q(q1 | q2))
get_invoiceable_partner(self, plan)

Return the invoiceable partner.

To be implemented by subclasses.

get_invoiceable_product(self, plan)

Return the product to put into the generated invoice item.

To be implemented by subclasses.

>>> obj = rt.models.courses.Enrolment.objects.all()[0]
>>> print(obj.get_invoiceable_product())
Journeys
get_invoiceable_qty(self)

Return the quantity to use for the generated invoice item.

May be overridden by subclasses. The default implementation simply returns default_invoiceable_qty.

>>> obj = rt.models.courses.Enrolment.objects.all()[0]
>>> print(obj.get_invoiceable_qty())
1
get_invoiceable_title(self, invoice=None)

Return the title to put into the generated invoice item.

May be overridden by subclasses.

invoicings

A GenericRelation to all invoice items pointing to this invoiceable.

This is preferred over get_invoicings().

get_invoicings(**kwargs)

Get a queryset with the invoicings that point to this invoiceable.

This is deprecated. Preferred way is to use invoicings.

get_last_invoicing()

Return the last invoicing that was created by this generator. According to the invoice's voucher_date.

allow_group_invoices()

Whether this is a grouping generator, i.e. the invoicings of which can be grouped together with those of other invoice generators into a same invoice.

class lino_xl.lib.invoicing.InvoicingInfo

A volatile object in memory that holds information about a given invoicing event.

generator

The invoice generator this is about.

max_date

The latest date of events considered when computing this.

invoicings

Existing invoice items generated by this generator for earlier periods.

invoiced_qty

Sum of quantities invoiced earlier.

invoiced_events

Number of events invoiced earlier.

used_events

A list of the "events" used for computing this.

invoiceable_product

Which fee to apply. If this is None, no invoicing should get generated.

Sales rules

Every partner can have a sales rule.

class lino_xl.lib.invoicing.SalesRule

The Django model used to represent a sales rule.

partner

The partner to which this sales rule applies.

invoice_recipient

The partner who should get the invoices caused by this partner.

paper_type

The default paper type to be used for invoicing.

>>> fld = rt.models.invoicing.SalesRule._meta.get_field('invoice_recipient')
>>> print(fld.help_text)
The partner who should get the invoices caused by this partner.
class lino_xl.lib.invoicing.SalesRules

Shows the list of sales rules.

Plugin settings

invoicing.order_model

The database model that represents an "invoicing order", a business document used by both partners as reference for invoicing.

In Presto this is orders.Order, in Noi this is subscriptions.Subscription.

invoicing.voucher_type
invoicing.voucher_model
invoicing.item_model

The database model of the items of generated invoices. Default value is sales.InvoiceItem.

invoicing.invoiceable_label

The verbose_name forthe InvoicingTargetItem.invoiceable field.

Invoicing rules

TODO: rename "flatrate" (the verbose name for Tariff) to "invoicing rule" or "invoicing asset".

Every product can have a flatrate.

class lino_xl.lib.invoicing.Tariff

The Django model used to represent a flatrate.

number_of_events

Number of invoicing events paid per invoicing.

For example in Lino Voga when a customer buys one ticket of ten, they can attend to 10 sessions.

Each time the customer buys a new flatrate, their asset increases by this number. The asset is what the customer did already pay for. When the asset is negative, Lino invoices the quantity needed to increase the asset to min_asset.

min_asset

The minimum number of invoicing events a customer should pay in advance.

Minimum quantity of invoicing events required to trigger an invoicing.

max_asset

Maximum quantity of invoicing events to allow per invoicing.

Never invoice more than this number of events (per invoicing period)

The invoicing plan

class lino_xl.lib.invoicing.Plan

The Django model used to represent an invoicing plan.

Inherits from lino.modlib.users.UserPlan.

Database fields:

user

The user who manages this plan.

invoicing_state

The invoicing state for which this plan is to generate invoices.

A pointer to Area.

target_journal

The journal into which invoices will be generated.

today

The date to be used for the invoices to generate.

min_date

Don't invoice events before this date. May be empty.

max_date

Don't invoice events after this date. If this is empty, Lino will use the day before the invoice date.

partner

Generate only for this partner.

order

Generate only for this invoicing order.

Row actions:

update_plan

Update this plan (fill the list of suggestions).

execute_plan

Execute this plan (create an invoice for each selected suggestion).

start_plan(user, **options)

Start an invoicing plan for the given user on the database object defined by k and v. Where k is the name of the field used to select the plan (e.g. 'partner' or 'journal') and v is the value for that field.

This will either create a new plan, or check whether the currently existing plan for this user was for the same database object. If it was for another object, then clear all items.

fill_plan(ar)

Add items to this plan, one for each invoice to generate.

This also groups the invoiceables by their invoiceable partner.

Note a case we had (20171007) : One enrolment for Alfons whose invoice_recipient points to Erna, a second enrolment for Erna directly. The first enrolment returned Erna as Partner, the second returned Erna as Pupil, so they were not grouped.

class lino_xl.lib.invoicing.Item

The Django model used to represent a item of an invoicing plan.

The items of an invoicing plan are called suggestions.

plan
partner
generator

The invoice generator that suggests this.

This is empty for items that were suggested by a grouping generator (InvoiceGenerator.allow_group_invoices() returns True) (even when only one generator made this suggestion).

preview

A textual preview of the invoiceable items to be included in the invoice.

amount
invoice

The invoice that has been generated. This field is empty for new items. When an item has been executed, this field points to the generated invoice.

workflow_buttons

The following fields are maybe not important:

first_date
last_date
number_of_invoiceables
create_invoice(ar):

Create the invoice corresponding to this item of the plan.

class lino_xl.lib.invoicing.Plans
class lino_xl.lib.invoicing.MyPlans
class lino_xl.lib.invoicing.AllPlans
class lino_xl.lib.invoicing.Items
class lino_xl.lib.invoicing.ItemsByPlan
class lino_xl.lib.invoicing.InvoicingsByInvoiceable
class lino_xl.lib.invoicing.StartInvoicing

Start an invoicing plan for the authenticated user.

Base for StartInvoicingForPartner.

Inherits from lino.modlib.users.StartPlan and just overrides the label.

class lino_xl.lib.invoicing.StartInvoicingByArea

Start an invoicing plan for this area.

This is installed onto the VouchersByJournal table of the VoucherType for the configured voucher_model as start_invoicing.

class lino_xl.lib.invoicing.StartInvoicingForPartner

Start an invoicing plan for this partner.

This is installed onto the contacts.Partner model as start_invoicing.

class lino_xl.lib.invoicing.StartInvoicingForOrder

Start an invoicing plan for this invoicing order.

class lino_xl.lib.invoicing.ExecutePlan

Execute this invoicing plan.

Create an invoice for each selected invoicing suggestion.

class lino_xl.lib.invoicing.ExecuteItem

Create an invoice for this invoicing suggestion.

class lino_xl.lib.invoicing.ToggleSelection

Invert selection status for all invoicing suggestions.

Invoicing areas

Invoicing areas are used in Lino Presto to differentiate between activities for which invoicing is often run manually based on occasional work and those that are invoiced monthly automatically based on regular work. In Lino Tera they might get used to separate the therapy centres in different towns. In Lino Noi this is used to differentiate between (monthly) service reports and (yearly) membership fees.

The application is responsible for selecting only invoiceables that belong to the area of the current plan. For example Lino Presto does this by defining a field lino_presto.lib.cal.Room.invoicing_area.

>>> rt.show(invoicing.InvoicingAreas)
========== ========= =================== =================
 value      name      text                target_journals
---------- --------- ------------------- -----------------
 invoices   default   Generate invoices   SLS
========== ========= =================== =================
>>> invoicing.InvoicingAreas.default.get_target_journals()
<QuerySet [Journal #1 ('Sales invoices (SLS)')]>
class lino_xl.lib.invoicing.Area

The Django model used to represent an invoicing area.

journal

The journal into which invoices are to be generated.

Manually editing automatically generated invoices

Resetting title and description of a generated invoice item

When the user sets title of an automatically generated invoice item to an empty string, then Lino restores the default value for both title and description

Invoice recipient

An invoice can point to up to three partners:

The invoice recipient is the only partner to enter into the accounting. On the other hand, the invoiceable partner is the first and most important partner for the users of the system.

That's why the partner attribute (field or property) of an invoice points to the customer (or provider, if it's a purchase document). And the invoice recipient will differ from the customer only when the partner has a salesrule__invoice_recipient field. And "delivery address" is just another custom field for those who want, it is not needed by the invoicing plugin.