ledger: General accounting

The lino_xl.lib.ledger plugin adds basic notions for accounting: accounts, journals, vouchers and movements.

Table of contents:

Examples in this document use the lino_book.projects.pierre demo project.

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

Overview

A ledger is a book in which the monetary transactions of a business are posted in the form of debits and credits (from 1).

In Lino, the ledger is implemented by three database models:

Voucher

Any document that serves as legal proof for a ledger transaction in the ledger. Examples of vouchers include invoices, bank statements, or payment orders.

Vouchers are stored in the database using some subclass of the Voucher model. The voucher model is never being used directly despite the fact that it is a concrete model.

Journal

A series of sequentially numbered vouchers.

Ledger movement

An atomic "transfer" of a given amount of money from (or to) a given ledger account at a given date. It is just a conceptual transfer, not a cash or bank transfer.

Moving money from (out of) an account is called "to debit", moving money to an account is called "to credit".

Movements are never created individually but by registering a voucher.

Ledger account

The most abstract representation for "something where you can place money and retrieve it later".

An account always has a given balance which can be negative or positive.

In applications which use the ledger plugin, accounts are used as the target of ledger movements.

Some more concepts:

Ledger transaction

The group of movements generated by a same voucher. For each transaction there must be at least two movements for which the sum of debited money equals the sum of credited money.

A transaction always happens at a given date and in a given accounting period which itself is part of a given fiscal year.

Database object

An entry in the database, represented by a "model instance".

Common account

A well-known account for which the site manager must configure a corresponding account of your accounts chart. See CommonAccounts.

Fiscal year

Usually (but not always) same as a calendar year. A sequence of accounting periods covered by an annual report. When the annual report has been published (declared to the national tax office), the fiscal year should be closed to prevent accidental changes in the ledger of that year.

Accounting period

Usually (but not always) same as a calendar month.

There are some secondary models and choice lists:

  • A match rule specifies that a movement into given account can be cleared using a given journal.

  • The payment term of an invoice (PaymentTerm) is a convention on how the invoice should be paid.

  • The ledger plug-in defines a list of voucher types which is filled by plug-ins like lino_xl.lib.vat, lino_xl.lib.sales or lino_xl.lib.vat who define some subclass of Voucher and use it for registering one or several voucher types.

And then there are many views for looking at this data.

Accounts

class lino_xl.lib.ledger.Account

Django model for representing a ledger account.

name

The multilingual designation of this account, as the users see it.

ref

An optional unique name which can be used to reference a given account.

type

The account type of this account. This points to an item of CommonAccounts.

needs_partner

Whether bookings to this account need a partner specified.

For payment orders this causes the contra entry of financial documents to be detailed or not (i.e. one contra entry for every item or a single contra entry per voucher.

vat_class

The default VAT class to use for transactions on this account.

default_amount

The default amount to book in bank statements or journal entries when this account has been selected manually. The default booking direction is that of the type.

purchases_allowed
sales_allowed
wages_allowed
clearings_allowed
FOO_allowed

These checkboxes indicate whether this account can be used on an item of a purchases (or sales or wages or FOO) invoice. There is one such checkbox for every trade type (TradeTypes). They exist only when the ledger plugin is installed as well. See also the get_allowed_accounts method.

needs_ana

Whether transactions on this account require the user to also specify an analytic account.

This file exists only when lino_xl.lib.ana is installed as well.

ana_account

Which analytic account to suggest for transactions on this account.

This file exists only when lino_xl.lib.ana is installed as well.

sheet_item

Pointer to the item of the balance sheet or income statement that will report the movements of this account.

This file is a dummy field when lino_xl.lib.sheets is not installed.

Common accounts

The accounts plugin defines a choicelist of common accounts which are used to reference the database object for certain accounts which have a special meaning.

class lino_xl.lib.ledger.CommonAccounts

The global list of common accounts.

This is a lino.core.choicelists.ChoiceList. Every item is an instance of CommonAccount.

This list is automatically sorted at startup because it is populated by several plugins, and because the natural sorting order would be useless and irritating.

class lino_xl.lib.ledger.CommonAccount

The base class for items of :CommonAccounts.

It defines two additional attributes:

clearable

Default value for Account.clearable.

needs_partner

Default value for Account.needs_partner.

get_object(self)

Return the database object representing this common account.

set_object(self, obj)

Set the cached database object representing this common account.

Called internally when Account.common_account is updated via web interface.

Here is the standard list of common accounts in a Lino Così application:

>>> rt.show(ledger.CommonAccounts, language="en")
... 
======= ========================= ========================= =========== ================================
 value   name                      text                      Clearable   Account
------- ------------------------- ------------------------- ----------- --------------------------------
 1000    net_income_loss           Net income (loss)         Yes         (1000) Net income (loss)
 4000    customers                 Customers                 Yes         (4000) Customers
 4300    pending_po                Pending Payment Orders    Yes         (4300) Pending Payment Orders
 4400    suppliers                 Suppliers                 Yes         (4400) Suppliers
 4500    employees                 Employees                 Yes         (4500) Employees
 4510    vat_due                   VAT due                   No          (4510) VAT due
 4511    vat_returnable            VAT returnable            No          (4511) VAT returnable
 4512    vat_deductible            VAT deductible            No          (4512) VAT deductible
 4513    due_taxes                 VAT declared              No          (4513) VAT declared
 4550    clearings                 Internal clearings        Yes         (4550) Internal clearings
 4600    tax_offices               Tax Offices               Yes         (4600) Tax Offices
 4900    waiting                   Waiting account           Yes         (4900) Waiting account
 5500    best_bank                 BestBank                  No          (5500) BestBank
 5700    cash                      Cash                      No          (5700) Cash
 6010    purchase_of_services      Purchase of services      No          (6010) Purchase of services
 6020    purchase_of_investments   Purchase of investments   No          (6020) Purchase of investments
 6040    purchase_of_goods         Purchase of goods         No          (6040) Purchase of goods
 6300    wages                     Wages                     No          (6300) Wages
 6900    net_income                Net income                No          (6900) Net income
 7000    sales                     Sales                     No          (7000) Sales
 7900    net_loss                  Net loss                  No          (7900) Net loss
======= ========================= ========================= =========== ================================

Lino applications can add specific items to that list or potentially redefine it completely

Debit and credit

lino_xl.lib.ledger.DEBIT
lino_xl.lib.ledger.CREDIT

Every movement of a financial transaction "moves" some amount either out of or into a given account. For some reasons beyond the scope of this book, accountants didn't want to express this "direction" of a movement simply by using either a positive or a negative number, they wanted an explicit word for it and called it debiting and crediting.

We represent the direction of a movement internally as the boolean values True and False, but define two names DEBIT and CREDIT for them:

>>> from lino_xl.lib.ledger.utils import DEBIT, CREDIT
>>> DEBIT
False
>>> CREDIT
True

Since it is a boolean field, some frontends might represent it as a checkbox. In that case remember that checked means credit and not checked means debit.

The balance of an account

The balance of an account is the amount of money in that account. An account balance is either Debit or Credit.

class lino_xl.lib.ledger.Balance

Light-weight object to represent a balance, i.e. an amount together with its booking direction (debit or credit).

Attributes:

d

The amount of this balance when it is debiting, otherwise zero.

c

The amount of this balance when it is crediting, otherwise zero.

A negative value on one side of the balance is automatically moved to the other side.

>>> from lino_xl.lib.ledger.utils import Balance
>>> Balance(10, -2)
Balance(12,0)

Database fields

class lino_xl.lib.ledger.DebitOrCreditField

A field that stores the "direction" of a movement, i.e. either DEBIT or CREDIT.

class lino_xl.lib.ledger.DebitOrCreditStoreField

Uused as lino_atomizer_class for DebitOrCreditField.

Movements

class lino_xl.lib.ledger.Movement

Represents an accounting movement in the ledger. See Overview.

value_date

The date at which this movement is to be entered into the ledger. This is usually the voucher's entry_date, except e.g. for bank statements where each item can have its own value date.

voucher

Pointer to the Voucher who caused this movement.

partner

Pointer to the partner involved in this movement.

If account has Account.needs_partner set, this may not be blank, otherwise it must be blank.

seqno

Sequential number within a voucher.

account

Pointer to the Account that is being moved by this movement.

debit

Virtual field showing amount if dc is DEBIT.

credit

Virtual field showing amount if dc is CREDIT.

amount
dc
match

Pointer to the Movement that is being cleared by this movement.

cleared

Whether

voucher_partner

A virtual field which returns the partner of the voucher. For incoming invoices this is the supplier, for outgoing invoices this is the customer, for financial vouchers this is empty.

A virtual field which shows a link to the voucher.

A virtual field which shows a clickable variant of the match string. Clicking it will open a table with all movements having that match.

ana_account

The analytic account to move together with this transactions.

This file exists only when lino_xl.lib.ana is installed as well.

class lino_xl.lib.ledger.Movements

The base table for all tables working on Movement. Defines filtering parameters and general behaviour.

start_period
end_period
start_date
end_date
cleared
journal_group
journal
year
project
partner
account
class lino_xl.lib.ledger.MovementsByPartner

The Movements linked to a given partner.

The summary of MovementsByPartner shows a balance. A negative number means that we owe money to this partner, a positive number means that this partner owes us money.

>>> obj = rt.models.contacts.Partner.objects.get(pk=125)
>>> rt.show(rt.models.ledger.MovementsByPartner, obj)
**1 open movements (1599.92 €)**
>>> rt.show(rt.models.ledger.MovementsByPartner, obj, nosummary=True)
============ =============== =================================== ============== ======== ================= =========
 Value date   Voucher         Description                         Debit          Credit   Match             Cleared
------------ --------------- ----------------------------------- -------------- -------- ----------------- ---------
 10/06/2016   *SLS 28/2016*   *(4000) Customers*                  1 599,92                **SLS 28/2016**   No
                              **Balance 1599.92 (1 movements)**   **1 599,92**
============ =============== =================================== ============== ======== ================= =========

Vouchers

class lino_xl.lib.ledger.Voucher

A Voucher is a document that represents a monetary transaction.

A voucher is never instantiated using this base model but using one of its subclasses. Examples of subclassed are sales.Invoice, vat.AccountInvoice (or vatless.AccountInvoice), finan.Statement etc...

This model is not abstract so that Movement can have a ForeignKey to a Voucher.

When the partner of an empty voucher has a purchase account, Lino automatically creates a voucher item using this account with empty amount.

state

The workflow state of this voucher. Choices are defined in VoucherStates

journal

The journal into which this voucher has been booked. This is a mandatory pointer to a Journal instance.

number

The sequence number of this voucher in the journal.

The voucher number is automatically assigned when the voucher is saved for the first time. The voucher number depends on whether yearly_numbering is enabled or not.

There might be surprising numbering if two users create vouchers in a same journal at the same time.

entry_date

The date of the journal entry, i.e. when this voucher is to journalized or booked.

voucher_date

The date on the voucher (i.e. when it has been issued by its emitter).

This is usually the same as entry_date. Exceptions may be invoices arriving after their fiscal year has been closed. Note that if you change entry_date of a voucher, then Lino will set the voucher_date to that date.

accounting_period

The accounting period to which this entry is to be assigned to. The default value is determined from entry_date.

If user changes this field, the number gets re-computed because it might change depending on the fiscal year of the accounting period.

"""

narration

A short explanation which ascertains the subject matter of this journal entry.

number_with_year
do_and_clear(func, do_clear)

Delete all movements of this voucher, then run the given callable func, passing it a set with all partners who had at least one movement in this voucher. The function is expected to add more partners to this set. Then call check_clearings() for all these partners.

create_movement(item, acc_tuple, project, dc, amount, **kw):

Create a movement for this voucher.

The specified item may be None if this the movement is caused by more than one item. It is used by DatedFinancialVoucher.

get_partner()

Return the partner related to this voucher. Overridden by PartnerRelated vouchers.

get_movement_description(self, ar)

Generate a series of HTML chunks to be displayed in the Movment.description field.

get_wanted_movements()

Subclasses must implement this. Supposed to return or yield a list of unsaved Movement instances.

get_mti_leaf(self):

Return the specialized form of this voucher.

From any Voucher instance we can get the actual document (Invoice, PaymentOrder, BankStatement, ...) by calling this method.

Registering a voucher

A voucher is always in one of the three states "Draft", "Registered" or "Cancelled". "Registering a voucher" means to change it status from "Draft" to "Registered".

The state of a voucher is stored in a field voucher_state. The available states and the rules for changing the state are called the workflow.

When a voucher is registered, it receives a sequence number in its Journal and Lino generates the movements according to the data in the voucher.

A registered voucher cannot be edited or deleted.

You can deregister a voucher at any moment (unless its fiscal year is archived).

When you deregister a voucher, all movements are deleted.

Journals

A journal is a named sequence of numbered vouchers.

>>> ses.show(ledger.Journals,
...     column_names="ref name trade_type account dc")
... 
=========== ============================ ============================ ===================== =============================== ===========================
 Reference   Designation                  Designation (en)             Trade type            Account                         Primary booking direction
----------- ---------------------------- ---------------------------- --------------------- ------------------------------- ---------------------------
 SLS         Factures vente               Sales invoices               Sales                                                 Credit
 SLC         Sales credit notes           Sales credit notes           Sales                                                 Debit
 PRC         Factures achat               Purchase invoices            Purchases                                             Debit
 PMO         Bestbank Payment Orders      Bestbank Payment Orders      Bank payment orders   (4300) Pending Payment Orders   Debit
 CSH         Caisse                       Cash                                               (5700) Cash                     Credit
 BNK         Bestbank                     Bestbank                                           (5500) BestBank                 Credit
 MSC         Miscellaneous transactions   Miscellaneous transactions                         (5700) Cash                     Credit
 SAL         Salaries                     Salaries                                           (5700) Cash                     Credit
=========== ============================ ============================ ===================== =============================== ===========================
class lino_xl.lib.ledger.Journal

Django model used to store journals. See Overview.

Fields:

ref
trade_type

Pointer to TradeTypes.

voucher_type

Pointer to an item of VoucherTypes.

journal_group

Pointer to an item of JournalGroups.

yearly_numbering

Whether the number of vouchers should restart at 1 every year.

force_sequence
account

The account to use for the counter-movements generated by vouchers in this journal.

partner

The partner to use as default partner for all vouchers in this journal.

printed_name
dc

The primary booking direction (checked means Credit, unchecked Debit).

In a journal of sales invoices this should be Debit (checked), because a positive invoice total should be debited from the customer's account.

In a journal of purchase invoices this should be Credit (not checked), because a positive invoice total should be credited to the supplier's account.

In a journal of bank statements this should be Debit (checked), because a positive balance change should be debited from the bank's general account.

In a journal of payment orders this should be Credit (not checked), because a positive total means an "expense" and should be credited from the journal's general account.

In all financial vouchers, the amount of every item increases the total if its direction is opposite of the primary direction.

auto_check_clearings

Whether to automatically check and update the 'cleared' status of involved transactions when (de)registering a voucher of this journal.

This can be temporarily disabled e.g. by batch actions in order to save time.

auto_fill_suggestions

Whether to automatically fill voucher item from due payments of the partner when entering a financial voucher.

template

See PrintableType.template.

sepa_account

Your bank account to specify in payment order.

Added by sepa : Communicating with the bank using SEPA.

class lino_xl.lib.ledger.Journals

List of all Journals. Accessible via Configure ‣ Accounting ‣ Journals.

class lino_xl.lib.ledger.JournalsOverview

The list of all Journals shown in the dashboard.

This is used as the primary dashboard item in Lino Così. It gives an idea of how much data is in the database, and it adds links for quickly opening a journal (which is after all one of the frequent actions in an accounting application).

>>> rt.show(ledger.JournalsOverview)
================================== ========= =========== ============ ============ ==========
 Description                        Total     This year   This month   Unfinished   Warnings
---------------------------------- --------- ----------- ------------ ------------ ----------
 Sales invoices (SLS)               **72**    **15**      **6**
 Sales credit notes (SLC)
 Purchase invoices (PRC)            **105**   **21**      **7**
 Bestbank Payment Orders (PMO)
 Cash (CSH)
 Bestbank (BNK)
 Miscellaneous transactions (MSC)
 Salaries (SAL)
 **Total (8 rows)**                 **177**   **36**      **13**       **0**
================================== ========= =========== ============ ============ ==========

Debit or credit

The "PCSD" rule: A purchase invoice credits the supplier's account, a sales invoice debits the customer's account.

>>> obj = vat.VatAccountInvoice.objects.order_by('id')[0]
>>> rt.show(ledger.MovementsByVoucher, obj)
============================= ========== =========== =========== ================ =========
 Account                       Partner    Debit       Credit      Match            Cleared
----------------------------- ---------- ----------- ----------- ---------------- ---------
 (4400) Suppliers              Bestbank               40,00       **PRC 1/2016**   No
 (6010) Purchase of services              40,00                                    Yes
                                          **40,00**   **40,00**
============================= ========== =========== =========== ================ =========
>>> obj = sales.VatProductInvoice.objects.order_by('id')[0]
>>> rt.show(ledger.MovementsByVoucher, obj)
================== ========== ============== ============== ================ =========
 Account            Partner    Debit          Credit         Match            Cleared
------------------ ---------- -------------- -------------- ---------------- ---------
 (4000) Customers   Bestbank   2 999,85                      **SLS 1/2016**   No
 (7000) Sales                                 2 999,85                        Yes
                               **2 999,85**   **2 999,85**
================== ========== ============== ============== ================ =========

So the balance of a supplier's account (when open) is usually on the credit side (they gave us money) while a customer's balance is usually on the debit side (they owe us money).

>>> from lino_xl.lib.ledger.utils import DCLABELS
>>> print(DCLABELS[ledger.TradeTypes.purchases.dc])
Credit
>>> print(DCLABELS[ledger.TradeTypes.sales.dc])
Debit

Ledger info

class lino_xl.lib.ledger.LedgerInfo

Django model used to store ledger specific information per user.

user

OneToOneField pointing to the user.

entry_date

The last value this user typed as entry_date of a voucher. It is the default value for every new voucher.

classmethod get_by_user(self, user)

Returns the ledger info entry for a given user.

Match rules

class lino_xl.lib.ledger.MatchRule

Django model used to store match rules.

Payment terms

class lino_xl.lib.ledger.PaymentTerm

Django model used to store payment terms.

The following fields define the default value for due_date:

days

Number of days to add to voucher_date.

months

Number of months to add to voucher_date.

end_of_month

Whether to move voucher_date to the end of month.

worker

The worker who pays or collects the invoice using Internal clearings.

printed_text

Used in sales/VatProductInvoice/trailer.html as follows:

{% if obj.payment_term.printed_text %}
{{parse(obj.payment_term.printed_text)}}
{% else %}
{{_("Payment terms")}} : {{obj.payment_term}}
{% endif %}

The printed_text field is important when using prepayments or other more complex payment terms. Lino uses a rather simple approach to handle prepayment invoices: only the global amount and the final due date is stored in the database, all intermediate amounts and due dates are just generated in the printable document. You just define one PaymentTerm row for each prepayment formula and configure your printed_text field. For example:

Prepayment <b>30%</b>
({{(obj.total_incl*30)/100}} {{obj.currency}})
due on <b>{{fds(obj.due_date)}}</b>, remaining
{{obj.total_incl - (obj.total_incl*30)/100}} {{obj.currency}}
due 10 days before delivery.

Accounting periods

class lino_xl.lib.ledger.AccountingPeriod

An accounting period is the smallest time slice to be observed (declare) in accounting reports. Usually it corresponds to one month. Except for some small companies which declare per quarter.

For each period it is possible to specify the exact dates during which it is allowed to register vouchers into this period, and also its "state": whether it is "closed" or not.

start_date
end_date
state
year
ref

Actors

class lino_xl.lib.ledger.Journals

The default table showing all instances of Journal.

class lino_xl.lib.ledger.ByJournal

Mixin for journal-based tables of vouchers.

class lino_xl.lib.ledger.Vouchers

The base table for all tables working on Voucher.

class lino_xl.lib.ledger.ExpectedMovements

A virtual table of DueMovement rows, showing all "expected" "movements (payments)".

Subclasses are DebtsByAccount and DebtsByPartner.

Also subclassed by lino_xl.lib.finan.SuggestionsByVoucher.

date_until

Show only movements whose booking date is before or on the given date.

trade_type

Show only movements in the given trade type.

from_journal

Show only movements generated by a voucher in the given journal.

for_journal

Show only movements that may be matched by the given journal (i.e. for which a match rule exists).

account

Show only movements on the given account.

partner

Show only movements with the given partner.

project

Show only movements about the given project.

show_sepa

Show only movements whose partner has a SEPA account.

same_dc

Show only movements having the same booking direction as the target voucher.

class lino_xl.lib.ledger.DebtsByAccount

The ExpectedMovements accessible by clicking the "Debts" action button on an account.

class lino_xl.lib.ledger.DebtsByPartner

This is the table being printed in a Payment Reminder. Usually this table has one row per sales invoice which is not fully paid. But several invoices ("debts") may be grouped by match. If the partner has purchase invoices, these are deduced from the balance.

This table is accessible by clicking the "Debts" action button on a Partner.

class lino_xl.lib.ledger.PartnerVouchers

Base class for tables of partner vouchers.

cleared
  • Yes : show only completely cleared vouchers.

  • No : show only vouchers with at least one open partner movement.

  • empty: don't care about movements.

class lino_xl.lib.ledger.AccountsBalance

A virtual table, the base class for different reports that show a list of accounts with the following columns:

ref description old_d old_c during_d during_c new_d new_c

Subclasses are :class:'GeneralAccountsBalance`, :class:'CustomerAccountsBalance` and :class:'SupplierAccountsBalance`.

class lino_xl.lib.ledger.GeneralAccountsBalance

An AccountsBalance for general accounts.

class lino_xl.lib.ledger.PartnerAccountsBalance

An AccountsBalance for partner accounts.

class lino_xl.lib.ledger.CustomerAccountsBalance

A PartnerAccountsBalance for the TradeType "sales".

class lino_xl.lib.ledger.SuppliersAccountsBalance

A PartnerAccountsBalance for the TradeType "purchases".

class lino_xl.lib.ledger.DebtorsCreditors

Abstract base class for different tables showing a list of partners with the following columns:

partner due_date balance actions

class lino_xl.lib.ledger.Debtors

Shows partners who have some debt against us. Inherits from DebtorsCreditors.

class lino_xl.lib.ledger.Creditors

Shows partners who give us some form of credit. Inherits from DebtorsCreditors.

Trade types

The trade type is one of the basic properties of every ledger operation which involves an external partner. Every partner movement is of one and only one trade type.

The default list of trade types is:

>>> rt.show(ledger.TradeTypes)
... 
======= =========== ===================== ========================================================== ================================================ =============================== =====================================
 value   name        text                  Main account                                               Base account                                     Product account field           Invoice account field
------- ----------- --------------------- ---------------------------------------------------------- ------------------------------------------------ ------------------------------- -------------------------------------
 S       sales       Sales                 *(4000) Customers* (Customers)                             *(7000) Sales* (Sales)                           Sales account (sales_account)
 P       purchases   Purchases             *(4400) Suppliers* (Suppliers)                             *(6040) Purchase of goods* (Purchase of goods)                                   Purchase account (purchase_account)
 W       wages       Wages                 *(4500) Employees* (Employees)                             *(6300) Wages* (Wages)
 T       taxes       Taxes                 *(4600) Tax Offices* (Tax Offices)                         *(4513) VAT declared* (VAT declared)
 C       clearings   Clearings             *(4550) Internal clearings* (Internal clearings)
 B       bank_po     Bank payment orders   *(4300) Pending Payment Orders* (Pending Payment Orders)
======= =========== ===================== ========================================================== ================================================ =============================== =====================================

Your application might have a different list. You can see the actually configured list for your site via Explorer ‣ Accounting ‣ Trade types.

class lino_xl.lib.ledger.TradeTypes

The choicelist with the trade types defined for this application.

The default configuration defines the following trade types:

sales

When you write an invoice to a customer and when the customer pays it.

purchases

When you get an invoice from a provider and when you pay it.

wages

When you write a payroll (declare the fact that you owe some wage to an employee) and later pay it (e.g. via a payment order).

clearings

When an employee declares that he paid some invoice for you, and later you pay that money back to his account. Or the employee collects money for a sales invoice and later returns that money to you. See Internal clearings.

bank_po

When you ask your bank to execute a payment, and later the bank debits your account.

Every trade type has the following properties.

class lino_xl.lib.ledger.TradeType

Base class for the choices of TradeTypes.

dc

The default booking direction.

main_account

The common account into which the total amount of partner vouchers (base + taxes) and their payments should be booked.

base_account

The default common account into which the base amount of any operation should be booked.

invoice_account_field_name

The name of a field to be injected on the Partner model which points to an account to be used instead of the default base_account.

base_account_field_name

The name of a field to be injected on the Product database model which points to an account to be used instead of the default base_account.

price_field

The name and label of the price field to be defined on the Product database model.

get_product_base_account(product)

Return the account into which the base amount of any operation of this rete type should be booked.

This is either the base account defined in the base_account_field_name for the given product, or the site-wide base_account.

get_catalog_price(product)

Return the catalog price of the given product for operations with this trade type.

get_partner_invoice_account(partner)

Return the account to use as default value for account invoice items. This is the invoice_account_field of the given partner and can be None.

Match rules

A match rule specifies that a movement into given account can be cleared using a given journal.

You can configure match rules either in the detail view of a journal or globally via Explorer ‣ Accounting ‣ Match rules.

This demo site has the following match rules:

>>> ses.show(ledger.MatchRules)
... 
==== =============================== ==================================
 ID   Account                         Journal
---- ------------------------------- ----------------------------------
 1    (4000) Customers                Sales invoices (SLS)
 2    (4000) Customers                Sales credit notes (SLC)
 3    (4400) Suppliers                Purchase invoices (PRC)
 4    (4000) Customers                Bestbank Payment Orders (PMO)
 5    (4400) Suppliers                Bestbank Payment Orders (PMO)
 6    (6300) Wages                    Bestbank Payment Orders (PMO)
 7    (4000) Customers                Cash (CSH)
 8    (4400) Suppliers                Cash (CSH)
 9    (6300) Wages                    Cash (CSH)
 10   (4300) Pending Payment Orders   Cash (CSH)
 11   (4000) Customers                Bestbank (BNK)
 12   (4400) Suppliers                Bestbank (BNK)
 13   (6300) Wages                    Bestbank (BNK)
 14   (4300) Pending Payment Orders   Bestbank (BNK)
 15   (4000) Customers                Miscellaneous transactions (MSC)
 16   (4400) Suppliers                Miscellaneous transactions (MSC)
 17   (6300) Wages                    Miscellaneous transactions (MSC)
 18   (4300) Pending Payment Orders   Miscellaneous transactions (MSC)
 19   (4000) Customers                Salaries (SAL)
 20   (4400) Suppliers                Salaries (SAL)
 21   (6300) Wages                    Salaries (SAL)
 22   (4300) Pending Payment Orders   Salaries (SAL)
==== =============================== ==================================

For example a payment order can be used to pay wages and suppliers invoices or (less frequently) to send back money that a customer had paid too much:

>>> jnl = ledger.Journal.objects.get(ref="PMO")
>>> rt.show(ledger.MatchRulesByJournal, jnl)
==================
 Account
------------------
 (4000) Customers
 (4400) Suppliers
 (6300) Wages
==================

Or a sales invoice can be used to clear another sales invoice:

>>> jnl = ledger.Journal.objects.get(ref="SLS")
>>> rt.show(ledger.MatchRulesByJournal, jnl)
==================
 Account
------------------
 (4000) Customers
==================

Debtors

Debtors are partners who received credit from us and therefore are in debt towards us. The most common debtors are customers, i.e. partners who received a sales invoice from us and did not yet pay that invoice.

Two debtors in the list below are not customers: Bestbank and the tax office. Bestbank is a debtor because pending payment orders are booked to this account. The tax office is a debtor because we had more VAT deductible (sales) than VAT due (purchases).

>>> ses.show(ledger.Debtors, column_names="partner partner_id balance")
... 
=================================== ========== ===============
 Partner                             ID         Balance
----------------------------------- ---------- ---------------
 Bestbank                            100        2 382,15
 Hans Flott & Co                     108        990,00
 Van Achter NV                       107        279,90
 Bernd Brechts Bücherladen           109        1 599,92
 Garage Mergelsberg                  105        1 188,58
 Ausdemwald Alfons                   116        770,00
 Reinhards Baumschule                110        2 349,81
 Arens Annette                       114        4 239,63
 Moulin Rouge                        111        951,82
 Altenberg Hans                      115        465,96
 Bastiaensen Laurent                 117        2 999,85
 Collard Charlotte                   118        2 039,82
 Auto École Verte                    112        525,00
 Charlier Ulrike                     119        679,81
 Dobbelstein Dorothée                124        990,00
 Ernst Berta                         125        1 599,92
 Evertz Bernd                        126        2 349,81
 Demeulenaere Dorothée               122        1 199,85
 Dobbelstein-Demeulenaere Dorothée   123        279,90
 Arens Andreas                       113        600,00
 Chantraine Marc                     120        280,00
 Faymonville Luc                     130        3 599,71
 Evers Eberhart                      127        951,82
 Dericum Daniel                      121        3 854,78
 Emonts Daniel                       128        525,00
 Gernegroß Germaine                  131        639,92
 Groteclaes Gregory                  132        465,96
 Hilgers Hildegard                   133        770,00
 Hilgers Henri                       134        2 999,85
 Johnen Johann                       138        3 319,78
 Engels Edgar                        129        600,00
 Jousten Jan                         140        279,90
 Ingels Irene                        135        2 039,82
 Kaivers Karl                        141        990,00
 Lambertz Guido                      142        1 599,92
 Jonas Josef                         139        1 199,85
 Jansen Jérémy                       136        959,81
 Laschet Laura                       143        3 301,63
 Mießen Michael                      148        465,96
 Malmendier Marc                     146        3 599,71
 Meessen Melissa                     147        639,92
 Jacobs Jacqueline                   137        535,00
 Meier Marie-Louise                  149        770,00
 Emonts Erich                        150        2 999,85
 Lazarus Line                        144        525,00
 Emontspool Erwin                    151        2 039,82
 Leffin Josefine                     145        600,00
 Emonts-Gast Erna                    152        679,81
 Radermacher Daniela                 156        1 199,85
 Radermacher Edgard                  157        279,90
 Radermacher Fritz                   158        2 589,92
 Radermacher Berta                   154        535,00
 Radermacher Christian               155        3 319,78
 di Rupo Didier                      164        639,92
 Radermacher Guido                   159        2 349,81
 da Vinci David                      165        1 235,96
 Radermacher Inge                    162        600,00
 Radermacher Alfons                  153        280,00
 Radermacher Jean                    163        3 599,71
 Radermacher Hans                    160        951,82
 Radermacher Hedi                    161        525,00
 **Total (61 rows)**                 **8229**   **87 821,22**
=================================== ========== ===============

The DebtsByPartner shows one row per uncleared invoice. For example here is the detail of the debts for partner 116 from above list:

>>> obj = contacts.Partner.objects.get(pk=116)
>>> obj
Partner #116 ('Ausdemwald Alfons')
>>> ses.show(ledger.DebtsByPartner, obj)
... 
==================== ============ ========================== ==========
 Due date             Balance      Debts                      Payments
-------------------- ------------ -------------------------- ----------
 13/04/2016           770,00       `SLS 18/2016 <Detail>`__
 **Total (1 rows)**   **770,00**
==================== ============ ========================== ==========

This shows that the partner received one sales invoice and did a partial payment on the same day.

Creditors are partners hwo gave us credit, IOW to whom we owe money. The most common creditors are providers, i.e. partners who send us a purchase invoice (which we did not yet pay).

>>> ses.show(ledger.Creditors, column_names="partner partner_id balance")
... 
===================== ========= ===============
 Partner               ID        Balance
--------------------- --------- ---------------
 Rumma & Ko OÜ         101       91,38
 Bäckerei Ausdemwald   102       8 368,19
 Donderweer BV         106       1 821,15
 Bäckerei Mießen       103       17 771,00
 Bäckerei Schmitz      104       48 194,90
 **Total (5 rows)**    **516**   **76 246,62**
===================== ========= ===============

Partner 101 from above list is both a supplier and a customer:

>>> obj = contacts.Partner.objects.get(pk=101)
>>> ses.show(ledger.DebtsByPartner, obj)
... 
===================== ============ ========================= ==========================
 Due date              Balance      Debts                     Payments
--------------------- ------------ ------------------------- --------------------------
 10/01/2016            -141,30                                `PRC 2/2016 <Detail>`__
 14/01/2016            2 039,82     `SLS 2/2016 <Detail>`__
 10/02/2016            -142,00                                `PRC 9/2016 <Detail>`__
 10/03/2016            -143,40                                `PRC 16/2016 <Detail>`__
 10/04/2016            -142,10                                `PRC 23/2016 <Detail>`__
 10/05/2016            -140,20                                `PRC 30/2016 <Detail>`__
 10/06/2016            -141,30                                `PRC 37/2016 <Detail>`__
 10/07/2016            -142,00                                `PRC 44/2016 <Detail>`__
 10/08/2016            -143,40                                `PRC 51/2016 <Detail>`__
 10/09/2016            -142,10                                `PRC 58/2016 <Detail>`__
 10/10/2016            -140,20                                `PRC 65/2016 <Detail>`__
 10/11/2016            -141,30                                `PRC 72/2016 <Detail>`__
 10/12/2016            -142,00                                `PRC 79/2016 <Detail>`__
 10/01/2017            -144,80                                `PRC 2/2017 <Detail>`__
 10/02/2017            -143,50                                `PRC 9/2017 <Detail>`__
 10/03/2017            -141,60                                `PRC 16/2017 <Detail>`__
 **Total (16 rows)**   **-91,38**
===================== ============ ========================= ==========================

Note that most numbers in above table are negative. A purchase invoice is a credit received from the provider, and we asked a list of debts by partner.

Fiscal years

Lino has a table of fiscal years. A fiscal year often corresponds to the calendar year, but not necessarily.

If lino_xl.lib.sheets is installed, the detail window of a FiscalYear object shows the financial reports (balance sheet and income statement) for this year.

class lino_xl.lib.ledger.FiscalYear
start_date
end_date
state
class lino_xl.lib.ledger.FiscalYears

The fiscal years available in this database.

The lino_xl.lib.ledger.fixtures.std fixture fills this table with 5 years starting from start_year.

>>> dd.plugins.ledger.start_year
2016
>>> dd.today()
datetime.date(2017, 3, 12)
>>> dd.today().year + 5
2022
>>> rt.show(ledger.FiscalYears)
... 
=========== ============ ============ =======
 Reference   Start date   End date     State
----------- ------------ ------------ -------
 2016        01/01/2016   31/12/2016   Open
 2017        01/01/2017   31/12/2017   Open
 2018        01/01/2018   31/12/2018   Open
 2019        01/01/2019   31/12/2019   Open
 2020        01/01/2020   31/12/2020   Open
 2021        01/01/2021   31/12/2021   Open
 2022        01/01/2022   31/12/2022   Open
=========== ============ ============ =======

Accounting periods

Each ledger movement happens in a given accounting period. An accounting period usually corresponds to a month of the calendar. Accounting periods are automatically created the first time they are needed by some operation.

>>> rt.show(ledger.AccountingPeriods)
... 
=========== ============ ============ ============= ======= ========
 Reference   Start date   End date     Fiscal year   State   Remark
----------- ------------ ------------ ------------- ------- --------
 2016-01     01/01/2016   31/01/2016   2016          Open
 2016-02     01/02/2016   29/02/2016   2016          Open
 2016-03     01/03/2016   31/03/2016   2016          Open
 2016-04     01/04/2016   30/04/2016   2016          Open
 2016-05     01/05/2016   31/05/2016   2016          Open
 2016-06     01/06/2016   30/06/2016   2016          Open
 2016-07     01/07/2016   31/07/2016   2016          Open
 2016-08     01/08/2016   31/08/2016   2016          Open
 2016-09     01/09/2016   30/09/2016   2016          Open
 2016-10     01/10/2016   31/10/2016   2016          Open
 2016-11     01/11/2016   30/11/2016   2016          Open
 2016-12     01/12/2016   31/12/2016   2016          Open
 2017-01     01/01/2017   31/01/2017   2017          Open
 2017-02     01/02/2017   28/02/2017   2017          Open
 2017-03     01/03/2017   31/03/2017   2017          Open
 2017-12     01/12/2017   31/12/2017   2017          Open
=========== ============ ============ ============= ======= ========

The reference of a new accounting period is computed by applying the voucher's entry date to the template defined in the date_to_period_tpl attribute of the ledger plugin. The default implementation leads to the following references:

>>> print(ledger.AccountingPeriod.get_ref_for_date(i2d(19940202)))
1994-02
>>> print(ledger.AccountingPeriod.get_ref_for_date(i2d(20150228)))
2015-02
>>> print(ledger.AccountingPeriod.get_ref_for_date(i2d(20150401)))
2015-04

You may manually create additional accounting periods. For example

  • 2015-00 might stand for a fictive "opening" period before January 2015 and after December 2014.

  • 2015-13 might stand for January 2016 in a company which is changing their fiscal year from "January-December" to "July-June".

Payment terms

>>> rt.show('ledger.PaymentTerms')
==================== ======================================= ======================================= ======== ========= ==============
 Reference            Designation                             Designation (en)                        Months   Days      End of month
-------------------- --------------------------------------- --------------------------------------- -------- --------- --------------
 07                   Payment seven days after invoice date   Payment seven days after invoice date   0        7         No
 10                   Payment ten days after invoice date     Payment ten days after invoice date     0        10        No
 30                   Payment 30 days after invoice date      Payment 30 days after invoice date      0        30        No
 60                   Payment 60 days after invoice date      Payment 60 days after invoice date      0        60        No
 90                   Payment 90 days after invoice date      Payment 90 days after invoice date      0        90        No
 EOM                  Payment end of month                    Payment end of month                    0        0         Yes
 P30                  Prepayment 30%                          Prepayment 30%                          0        30        No
 PIA                  Payment in advance                      Payment in advance                      0        0         No
 **Total (8 rows)**                                                                                   **0**    **227**
==================== ======================================= ======================================= ======== ========= ==============

Journal groups

class lino_xl.lib.ledger.JournalGroup
menu_group

The name of another plugin

For each journal group there will be a menu item in the main menu.

If the journal group has a menu_group, then journals are added to the menu of the named plugin, otherwise to the menu of the ledger plugin.

class lino_xl.lib.ledger.JournalGroups

The list of possible journal groups.

This list is used to build the main menu. Journals whose journal_group is empty will not be available through the main user menu. See also JournalGroup.menu_group.

The default configuration defines the following journal groups:

>>> rt.show(ledger.JournalGroups)
... 
======= =========== ============================
 value   name        text
------- ----------- ----------------------------
 10      sales       Sales
 20      purchases   Purchases
 30      wages       Wages
 40      financial   Financial
 50      vat         VAT
 60      misc        Miscellaneous transactions
======= =========== ============================
sales

For sales journals.

purchases

For purchases journals.

wages

For wages journals.

financial

For financial journals (bank statements and cash reports)

class lino_xl.lib.ledger.PeriodStates

The list of possible states of an accounting period.

open
closed

Voucher types

class lino_xl.lib.ledger.VoucherTypes

The list of voucher types available in this application. Each items is an instances of :class:VoucherType`.

The voucher_type field of a journal points to an item of this.

get_for_model()
get_for_table()
class lino_xl.lib.ledger.VoucherType

Base class for all items of VoucherTypes.

The voucher type defines the database model used to store vouchers of this type (model).

But it can be more complex: actually the voucher type is defined by its table_class, i.e. application developers can define more than one voucher type per model by providing alternative tables (views) for it.

Every Lino Cosi application has its own global list of voucher types defined in the VoucherTypes choicelist.

model

The database model used to store vouchers of this type. A subclass of lino_xl.lib.ledger.models.Voucher`.

table_class

Must be a table on model and with master_key set to the journal.

class lino_xl.lib.ledger.VoucherState

Base class for items of VoucherStates.

editable

Whether a voucher in this state is editable.

class lino_xl.lib.ledger.VoucherStates

The list of possible states of a voucher.

In a default configuration, vouchers can be draft, registered, cancelled or signed.

draft

Draft vouchers can be modified but are not yet visible as movements in the ledger.

registered

Registered vouchers cannot be modified, but are visible as movements in the ledger.

cancelled

Cancelled is similar to Draft, except that you cannot edit the fields. This is used for invoices which have been sent, but the customer signaled that they doen't agree. Instead of writing a credit nota, you can decide to just cancel the invoice.

signed

The Signed state is similar to registered, but cannot usually be deregistered anymore. This state is not visible in the default configuration. In order to make it usable, you must define a custom workflow for VoucherStates.

Model mixins

class lino_xl.lib.ledger.SequencedVoucherItem

A VoucherItem which also inherits from lino.mixins.sequenced.Sequenced.

class lino_xl.lib.ledger.AccountVoucherItem

Abstract base class for voucher items which point to an account.

This is also a SequencedVoucherItem.

This is subclassed by lino_xl.lib.vat.models.InvoiceItem and lino_xl.lib.vatless.models.InvoiceItem.

It defines the account field and some related methods.

account

ForeignKey pointing to the account (ledger.Account) that is to be moved.

class lino_xl.lib.ledger.VoucherItem

Base class for items of a voucher.

Subclasses must define the following fields:

voucher

Pointer to the voucher which contains this item. Non nullable. The voucher must be a subclass of ledger.Voucher. The related_name must be 'items'.

title

The title of this voucher.

Currently (because of Django ticket #19465), this field is not implemented here but in the subclasses:

lino_xl.lib.vat.models.AccountInvoice lino_xl.lib.vat.models.InvoiceItem

class lino_xl.lib.ledger.Matching

Model mixin for database objects that are considered matching transactions. A matching transaction is a transaction that points to some other movement which it "clears" at least partially.

A movement is cleared when its amount equals the sum of all matching movements.

Adds a field match and a chooser for it. Requires a field partner. The default implementation of the chooser for match requires a journal.

Base class for lino_xl.lib.vat.AccountInvoice (and e.g. lino_xl.lib.sales.Invoice, lino_xl.lib.finan.DocItem)

match

Pointer to the movement which is being cleared by this movement.

class lino_xl.lib.ledger.PartnerRelated

Base class for things that are related to one and only one trade partner. This is base class for both (1) trade document vouchers (e.g. invoices or offers) and (2) for the individual entries of financial vouchers and ledger movements.

partner

The recipient of this document. A pointer to lino_xl.lib.contacts.models.Partner.

payment_term

The payment terms to be used in this document. A pointer to PaymentTerm.

recipient

Alias for the partner

class lino_xl.lib.ledger.ProjectRelated

Model mixin for objects that are related to a project.

project

Pointer to the "project". This field exists only if the project_model setting is nonempty.

class lino_xl.lib.ledger.PeriodRange

Model mixin for objects that consider, cover or observe a range of accounting periods.

start_period

The period which marks the beginning of the range to consider.

end_period

Leave empty if you want only one period (specified in start_period). If this is non-empty, all periods between and including these two are to be considered.

class lino_xl.lib.ledger.PeriodRangeObservable

Model mixin for objects that can be filtered by a range of accounting periods. This adds two fields start_period and end_period to the parameter fields.

class lino_xl.lib.ledger.ItemsByVoucher

Shows the items of this voucher.

This is used as base class for slave tables in lino_xl.lib.finan, lino_xl.lib.vat, lino_xl.lib.vatless, lino_xl.lib.ana, ...

Utilities

class lino_xl.lib.ledger.DueMovement

A volatile object representing a group of matching movements.

A due movement is a movement which a partner should do in order to clear their debt. Or which we should do in order to clear our debt towards a partner.

The "matching" movements of a given movement are those whose match, partner and account fields have the same values.

These movements are themselves grouped into "debts" and "payments". A "debt" increases the debt and a "payment" decreases it.

match

The common match string of these movments

dc

Whether I mean my debts and payments (towards that partner) or those of the partner (towards me).

partner
account
lino_xl.lib.ledger.get_due_movements(dc, flt)

Generates a series of DueMovement objects which --if they were booked-- would clear the movements given by the filter condition flt.

There will be at most one DueMovement per (account, partner, project, match), each of them grouping the movements with same partner, account, project and match.

This is the data source for ExpectedMovements and subclasses.

The balances of the DueMovement objects will be positive or negative depending on the specified dc.

Arguments:

Dc

(boolean): The target booking direction, i.e. which direction should be considered positive. Open movements in the opposite direction will be negative.

Flt

Optional filter arguments to give to Django's filter() method in order to specifiy which Movement objects to consider.

lino_xl.lib.ledger.check_clearings(qs, matches=[])

Check whether involved movements are cleared or not, and update their cleared field accordingly.

lino_xl.lib.ledger.check_clearings_by_account(account, matches=[])

Call check_clearings() for the given ledger account.

lino_xl.lib.ledger.check_clearings_by_partner(partner, matches=[])

Call check_clearings() for the given partner.

Plugin attributes

See lino_xl.lib.ledger.Plugin.

Mixins

class lino_xl.lib.ledger.AccountBalances

A table which shows a list of general ledger accounts during the observed period, showing their old and new balances and the sum of debit and credit movements.

class lino_xl.lib.ledger.AccountingPeriodRange

A parameter panel with two fields:

start_period

Start of observed period range.

end_period

Optional end of observed period range. Leave empty to consider only the Start period.

The Y2K problem

Lino supports accounting across milleniums.

>>> FiscalYear = rt.models.ledger.FiscalYear
>>> print(FiscalYear.year2ref(1985))
1985
>>> print(FiscalYear.year2ref(9985))
9985

But there are legacy systems where the year was internally represented using a two-letter code.

The fix_y2k is either True or False.

>>> dd.plugins.ledger.fix_y2k
False
>>> dd.plugins.ledger.fix_y2k = True
>>> print(FiscalYear.year2ref(1985))
85
>>> print(FiscalYear.year2ref(1999))
99
>>> print(FiscalYear.year2ref(2000))
A0
>>> print(FiscalYear.year2ref(2015))
B5
>>> print(FiscalYear.year2ref(2135))
N5
>>> print(FiscalYear.year2ref(2259))
Z9
>>> print(FiscalYear.year2ref(2260))
[0

The on_ledger_movement signal

lino_xl.lib.ledger.on_ledger_movement

Custom signal sent when a partner has had at least one change in a ledger movement.

  • sender the database model

  • instance the partner

Don't read me

Until 20181016 it was not possible to manually reverse the sort order of a virtual field having a sortable_by which contained itself a reversed field. The Movement.credit field is an example:

>>> rmu(ledger.Movement.get_data_elem('credit').sortable_by)
['-amount', 'value_date']
>>> par = contacts.Partner.objects.get(pk=122)
>>> url = "api/ledger/MovementsByPartner?fmt=json&mk=122&mt=17"
>>> args = ('count rows no_data_text success title param_values', 1)
>>> demo_get('robin', url + "&sort=credit&dir=ASC", *args)

The following failed before 20181016:

>>> demo_get('robin', url + "&sort=credit&dir=DESC", *args)

Templates

payment_reminder.body.html

Defines the body text of a payment reminder.

base.weasy.html
payment_reminder.weasy.html

Defines the body text of a payment reminder.

Generating counter-entries

A payment order generates counter entries

If you want Lino to suggest the cleaning of payment orders when entering bank statements, then create a an organization (contacts.Company) representing your bank and have the Journal.partner field point to that partner.

Note that the journal must also have an account with Account.needs_partner enabled in order to prevent Lino from generating detailed counter-entries (one per item). Clearing a payment order makes sense only when the counter-entry is the sum of all movements.