Welcome | Get started | Dive into Lino | Contribute | Topics | Reference | More

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.apc demo project.

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

List of partners who are both supplier and customer and have open movements:

>>> from lino_xl.lib.ledger.choicelists import TradeTypes
>>> def has_mvt(obj, tt):
...     qs = ledger.Movement.objects.filter(partner=obj, cleared=False, voucher__journal__trade_type=tt)
...     return qs.count()
>>> for p in contacts.Partner.objects.all():
...     if has_mvt(p, TradeTypes.purchases) and has_mvt(p, TradeTypes.sales):
...         print(p.pk, p)

Overview

Ledger movements are never created individually but by registering a ledger voucher.

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.

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

There are many views for looking at accounting data.

Plugin configuration settings

Here is a list of the plugin settings for this plugin.

ledger.ref_length

The max_length of the Reference field of a ledger account.

ledger.currency_symbol

The currency symbol to use when no currency is set.

Temporary approach until we add support for multiple currencies. See also lino.core.site.Site.format_currency().

ledger.use_pcmn

Whether to use the PCMN notation.

PCMN stands for "plan compatable minimum normalisé" and is a standardized nomenclature for accounts used in France and Belgium.

ledger.project_model

Leave this to None for normal behaviour. Set this to a string of the form '<app_label>.<ModelName>' if you want to add an additional field project to all models which inherit from ProjectRelated.

ledger.worker_model

The model to use for workers.

Default value is None. If this is set to a model name (e.g. 'contacts.Person'), Lino will add a field PaymentTerm.worker.

ledger.start_year

An integer with the calendar year in which this site starts working.

This is used to fill the default list of FiscalYears, and by certain fixtures for generating demo invoices.

ledger.fix_y2k

Whether to use a Y2K compatible representation for fiscal years.

ledger.suppress_movements_until

Don't create any movements before that date. Vouchers can exist and get registered before that date, but they don't have any influence to the ledger.

This is useful e.g. when you want to keep legacy vouchers in your database but not their movments.

ledger.sales_method

Which sales-related journals to create on a new site and how they collaborate. The resulting demo data also depends on whether the trading and/or invoicing plugins are installed.

ledger.has_payment_methods

Whether this Lino site knows about payment methods and cash invoices (both used on a point of sale).

User roles

class lino_xl.lib.ledger.LedgerPartner

Can see transactions related to their partner account.

class lino_xl.lib.ledger.AccountingReader

Can read all accounting data and create reports, but cannot change any relevant data.

class lino_xl.lib.ledger.LedgerUser

Can see all journals, create vouchers of any kind, can see vouchers of other users but cannot edit them.

class lino_xl.lib.ledger.VoucherSupervisor

Can edit vouchers that have been written by other users.

class lino_xl.lib.ledger.LedgerStaff

Can configure ledger functionality.

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 counter entry of financial documents to be detailed or not (i.e. one contra entry for every item or a single counter 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

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
 4100    suppliers                 Suppliers                 Yes         (4100) Suppliers
 4200    employees                 Employees                 Yes         (4200) Employees
 4300    pending_po                Pending Payment Orders    Yes         (4300) Pending Payment Orders
 4500    tax_offices               Tax Offices               Yes         (4500) Tax Offices
 4510    vat_due                   VAT due                   No          (4510) VAT due
 4513    due_taxes                 VAT declared              No          (4513) VAT declared
 4520    vat_deductible            VAT deductible            No          (4520) VAT deductible
 4530    vat_returnable            VAT returnable            No          (4530) VAT returnable
 4800    clearings                 Internal clearings        Yes         (4800) Internal clearings
 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
======= ========================= ========================= =========== ================================

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

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.

waiting

The waiting account, used to temporarily book movements for which you do not know where to book them.

undeclared_costs

Used to books costs that will be reculated internally and are irrelevant for VAT declaration and annual report.

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.

Keep in mind that common accounts are no database objects. See them rather as a list of configuration values. They are just a list of named pointers to actual database objects.

For example you might want to know how many sales operations are in your database:

>>> obj = ledger.CommonAccounts.sales.get_object()
>>> obj
Account #20 ('(7000) Sales')
>>> ledger.Movement.objects.filter(account=obj).count()
92

A common account neither requires nor makes sure that its database row exists. For example the common account "Net loss" has no database object in the accounts chart pointing to it. The above trick won't work for counting the number of net loss operations:

>>> obj = ledger.CommonAccounts.net_loss.get_object()
>>> obj
MissingRow('No Account pointing to <ledger.CommonAccounts.net_loss:7900>')
>>> print(obj)
MissingRow(No Account pointing to <ledger.CommonAccounts.net_loss:7900>)
>>> ledger.Movement.objects.filter(account=obj).count()
Traceback (most recent call last):
...
TypeError: Field 'id' expected a number but got MissingRow('No Account pointing to <ledger.CommonAccounts.net_loss:7900>').

Debit and credit

Every journal has its specific default booking direction (configured in Journal.dc). For example a (positive) amount in a sales invoice means the opposite direction of a (positive) amount in a purchase invoice.

See also The Accounting Equation.

When migrating from Lino before 20201008, keep in mind that that a checked dc field meant credit and not checked meant debit.

class lino_xl.lib.ledger.DC

A choicelist with the two values "debit" and "credit".

It can be used e.g. to express the "expected" or "normal" booking direction for a journal, account or field in an accounting report.

>>> rt.show(ledger.DC)
======= ======== ========
 value   name     text
------- -------- --------
 D       debit    Debit
 C       credit   Credit
======= ======== ========

For the following code examples we import it:

>>> from lino_xl.lib.ledger.choicelists import DC

The balance of an account

The balance of an account is the amount of money in that account. An account balance is either debiting or crediting.

class lino_xl.lib.ledger.Balance

A light-weight object to represent a balance, i.e. an amount together with its booking direction (debiting or crediting).

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.

>>> from lino_xl.lib.ledger.utils import Balance
>>> b = Balance(10, 2)
>>> b
Balance(8,0)
>>> print(b)
8 DB
>>> b.value(DC.debit)
Decimal('8')
>>> Balance(15, 23)
Balance(0,8)

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

>>> Balance(10, -2)
Balance(12,0)
>>> Balance(10, 2) + Balance(15, 23)
Balance(0,0)
>>> from decimal import Decimal
>>> Balance(Decimal("12.34"), Decimal("12.33"))
Balance(0.01,0)

Database fields

class lino_xl.lib.ledger.DebitOrCreditField

After 20201008 this is replaced by DC.field().

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

class lino_xl.lib.ledger.DebitOrCreditStoreField

No longer used after 20201008.

Used as lino_atomizer_class for DebitOrCreditField.

Movements

class lino_xl.lib.ledger.Movement

Django model used to represent a ledger movement

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 ledger voucher that 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 having ledger movements as rows.

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

Shows the ledger movements linked to a given partner.

class lino_xl.lib.ledger.MovementsByAccount

Shows the ledger movements done on a given general account.

description

A virtual field showing a comma-separated list of the following items:

  • voucher narration

  • voucher partner

  • transaction's partner

  • transaction's project

class lino_xl.lib.ledger.MovementsByMatch

Show all movements having a given Movement.match.

This is another example of a slave table whose master is not a database object, and the first example of a slave table whose master is a simple string.

class lino_xl.lib.ledger.MovementsByProject

Show the ledger movements of a project.

class lino_xl.lib.ledger.AllMovements

Show all the ledger movements in the database.

Displayed by Explorer ‣ Accounting ‣ Movements.

class lino_xl.lib.ledger.MovementsByVoucher

Show the ledger movements generated by a given voucher.

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.

For example David da Vinci has 4 open invoices:

>>> obj = rt.models.contacts.Person.objects.get(pk=165)
>>> obj
Person #165 ('Mr David da Vinci')
>>> rt.show(rt.models.ledger.MovementsByPartner, obj)
**2 open movements (-1961.38 €)**
>>> rt.show(rt.models.ledger.MovementsByPartner, obj, nosummary=True)
============ =============== ======================================= ============== ======== ============= =========
 Value date   Voucher         Description                             Debit          Credit   Match         Cleared
------------ --------------- --------------------------------------- -------------- -------- ------------- ---------
 12/03/2015   *SLS 15/2015*   *(4000) Customers* | *da Vinci David*   1 314,03                SLS 15/2015   No
 11/03/2015   *SLS 14/2015*   *(4000) Customers* | *da Vinci David*   647,35                  SLS 14/2015   No
                              **Balance 1961.38 (2 movements)**       **1 961,38**
============ =============== ======================================= ============== ======== ============= =========

Vouchers

class lino_xl.lib.ledger.Voucher

Django model used to represent a ledger voucher.

This model is not abstract because we want Movement to have a ForeignKey to a Voucher.

A voucher is never instantiated using this base model but using one of its subclasses. Here are the voucher subclasses available in Lino Così:

>>> pprint(rt.models_by_base(ledger.Voucher))
[<class 'lino_xl.lib.bevat.models.Declaration'>,
 <class 'lino_xl.lib.finan.models.BankStatement'>,
 <class 'lino_xl.lib.finan.models.JournalEntry'>,
 <class 'lino_xl.lib.finan.models.PaymentOrder'>,
 <class 'lino_xl.lib.ledger.models.Voucher'>,
 <class 'lino_xl.lib.trading.models.VatProductInvoice'>,
 <class 'lino_xl.lib.vat.models.VatAccountInvoice'>]

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 state of this voucher. It decides among others whether you can edit this voucher or not.

This field is defined by the implementing voucher class, which depends on the journal's voucher type.

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 within its 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 be 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 use when booking this voucher. 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 to explain the subject matter of this journal entry.

number_with_year

Shows the accounting year and the number of this voucher within its journal.

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 lino_xl.lib.contacts.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.

Class inheritance diagram

Inheritance diagram of lino_xl.lib.ledger.models.Voucher

Registering a voucher

class lino_xl.lib.ledger.LedgerRegistrable
toggle_state

Toggle between "registered" and "draft" state.

A one-click action to quickly toggle between the two the most-used states of a voucher. Represented in the toolbar as a button.

>>> finan.BankStatement.toggle_state.help_text
'Toggle between "registered" and "draft" state.'
hide_editable_number

Whether to hide the number that will be used for this voucher in its journal as long as the voucher is in an editable state.

We usually don't want to see the number of a voucher in an editable state because that number may change. We prefer to see the primary key prefixed with a hash to indicate that the voucher is not registered. But e.g. in lino_xl.lib.orders we want to disable this feature.

NB we might simply override __str__(), but maybe this feature will be used in other contexts as well.

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.

class lino_xl.lib.ledger.ToggleState

The action behind LedgerRegistrable.toggle_state.

Journals

Here is the list of all journals.

>>> ses.show(ledger.Journals,
...     column_names="ref name trade_type account dc")
... 
=========== ========================== ============================ ============================ ===================== =============================== ===========================
 Reference   Designation                Designation (fr)             Designation (en)             Trade type            Account                         Primary booking direction
----------- -------------------------- ---------------------------- ---------------------------- --------------------- ------------------------------- ---------------------------
 SLS         Verkaufsrechnungen         Factures vente               Sales invoices               Sales                                                 Credit
 SLC         Gutschriften Verkauf       Notes de crédit vente        Sales credit notes           Sales                                                 Debit
 PRC         Einkaufsrechnungen         Factures achat               Purchase invoices            Purchases                                             Debit
 PMO         Zahlungsaufträge           Ordre de paiement Bestbank   Bestbank Payment Orders      Bank payment orders   (4300) Pending Payment Orders   Credit
 CSH         Kassenbuch                 Livre de caisse              Cash book                                          (5700) Cash                     Credit
 BNK         Bestbank                   Bestbank                     Bestbank                                           (5500) BestBank                 Credit
 MSC         Diverse Buchungen          Opérations diverses          Miscellaneous transactions                         (5700) Cash                     Credit
 PRE         Preliminary transactions   Preliminary transactions     Preliminary transactions                           (5700) Cash                     Credit
 SAL         Lohnscheine                Fiches de paie               Paychecks                                          (5700) Cash                     Debit
 VAT         MwSt.-Erklärungen          Déclarations TVA             VAT declarations             Taxes                 (4513) VAT declared             Debit
=========== ========================== ============================ ============================ ===================== =============================== ===========================
class lino_xl.lib.ledger.Journal

Django model used to represent a journal.

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
make_ledger_movements

Whether vouchers in this journal generate ledger movements.

For example, a journal "Delivery notes" or "Offers" generally doesn't cause ledger movements.

preliminary

Whether transactions in this journal are considered preliminary.

account

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

partner

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

printed_name
must_declare

Whether movements made by this journal should be included in VAT declarations.

dc

The primary booking direction. Voucher items in this direction increase the total amount of the voucher.

In a journal of sales invoices this should be Credit because a positive invoice item should credit the turnover account (and hence their sum will debit the customers receivable account).

In a journal of purchase invoices this should be Debit because a positive invoice item should debit the cost account (and hence their sum will credit the suppliers payable account).

In a journal of bank statements this should be Credit because a crediting item (income) should increase the balance of the bank account while a debiting item (expense) should decrease it.

In a journal of payment orders this should be Debit because a positive total means an expense to be debited from the pending payment orders account (see CommonAccounts).

In a journal of paychecks this should be Debit because a positive paycheck item should debit the wages account (and hence their sum will credit the employees payable account).

auto_check_clearings

Whether to automatically check and update the 'cleared' status of ledger movements 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.login("robin").show(ledger.JournalsOverview)
... 
**72 Sales invoices (SLS)** **⊕**
**0 Sales credit notes (SLC)** **⊕**
**105 Purchase invoices (PRC)** **⊕**
**14 Bestbank Payment Orders (PMO)** **⊕**
**0 Cash book (CSH)** **⊕**
**14 Bestbank (BNK)** **⊕**
**0 Miscellaneous transactions (MSC)** **⊕**
**1 Preliminary transactions (PRE)** **⊕**
**0 Paychecks (SAL)** **⊕**
**14 VAT declarations (VAT)** **⊕**
>>> rt.login("robin").show(ledger.JournalsOverview, nosummary=True)
... 
======================================================== ========= =========== ============ ============ ==========
 Description                                              Total     This year   This month   Unfinished   Warnings
-------------------------------------------------------- --------- ----------- ------------ ------------ ----------
 Sales invoices (SLS) / **New Invoice**                   **72**    **15**      **6**
 Sales credit notes (SLC) / **New Credit note**
 Purchase invoices (PRC) / **New Invoice**                **105**   **21**      **7**
 Bestbank Payment Orders (PMO) / **New Payment order**    **14**    **2**
 Cash book (CSH) / **New Cash statement**
 Bestbank (BNK) / **New Bank statement**                  **14**    **2**
 Miscellaneous transactions (MSC) / **New Transaction**
 Preliminary transactions (PRE) / **New Transaction**     **1**
 Paychecks (SAL) / **New Paycheck**
 VAT declarations (VAT) / **New VAT declaration**         **14**    **2**
 **Total (10 rows)**                                      **220**   **42**      **13**       **0**
======================================================== ========= =========== ============ ============ ==========

Class inheritance diagram

Inheritance diagram of lino_xl.lib.ledger.models.Journal

Debit or credit? The PCSD rule

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(vat.MovementsByVoucher, obj)
============================= ========== =========== =========== ================================ ================ =========
 Account                       Partner    Debit       Credit      VAT class                        Match            Cleared
----------------------------- ---------- ----------- ----------- -------------------------------- ---------------- ---------
 (6010) Purchase of services              33,06                   Goods at normal VAT rate (21%)                    Yes
 (4520) VAT deductible                    6,94                    Goods at normal VAT rate (21%)                    Yes
 (4100) Suppliers              Bestbank               40,00                                        **PRC 1/2014**   Yes
                                          **40,00**   **40,00**
============================= ========== =========== =========== ================================ ================ =========
>>> obj = trading.VatProductInvoice.objects.order_by('id')[0]
>>> rt.show(vat.MovementsByVoucher, obj)
================== ========== ============== ============== =========== ================ =========
 Account            Partner    Debit          Credit         VAT class   Match            Cleared
------------------ ---------- -------------- -------------- ----------- ---------------- ---------
 (7000) Sales                                 2 999,85       Services                     Yes
 (4510) VAT due                               629,97         Services                     Yes
 (4000) Customers   Bestbank   3 629,82                                  **SLS 1/2014**   Yes
                               **3 629,82**   **3 629,82**
================== ========== ============== ============== =========== ================ =========

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).

>>> print(ledger.TradeTypes.purchases.dc)
Credit
>>> print(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

>>> rt.show(ledger.PaymentTerms)
... 
==================== ==================================== ==================================== ======================================= ======== ========= ============== =================
 Reference            Designation                          Designation (fr)                     Designation (en)                        Months   Days      End of month   Worker
-------------------- ------------------------------------ ------------------------------------ --------------------------------------- -------- --------- -------------- -----------------
 07                   Zahlung sieben Tage Rechnungsdatum   Zahlung sieben Tage Rechnungsdatum   Payment seven days after invoice date   0        7         No
 10                   Zahlung zehn Tage Rechnungsdatum     Zahlung zehn Tage Rechnungsdatum     Payment ten days after invoice date     0        10        No
 30                   Zahlung 30 Tage Rechnungsdatum       Zahlung 30 Tage Rechnungsdatum       Payment 30 days after invoice date      0        30        No
 60                   Zahlung 60 Tage Rechnungsdatum       Zahlung 60 Tage Rechnungsdatum       Payment 60 days after invoice date      0        60        No
 90                   Zahlung 90 Tage Rechnungsdatum       Zahlung 90 Tage Rechnungsdatum       Payment 90 days after invoice date      0        90        No
 EOM                  Zahlung Monatsende                   Zahlung Monatsende                   Payment end of month                    0        0         Yes
 P30                  Anzahlung 30%                        Anzahlung 30%                        Prepayment 30%                          0        30        No
 PIA                  Vorauszahlung                        Vorauszahlung                        Payment in advance                      0        0         No
 robin                Cash Robin                           Cash Robin                           Cash Robin                              0        0         No             Mr Robin Dubois
 **Total (9 rows)**                                                                                                                     **0**    **227**
==================== ==================================== ==================================== ======================================= ======== ========= ============== =================
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 trading/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.

Payment methods

class lino_xl.lib.ledger.PaymentMethod

Django model used to store payment methods.

Exists only when ledger.has_payment_methods it True.

The following fields define the default value for due_date:

payment_account

Which ledger account to book.

is_cash

Whether this is considered a cash payment.

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.ByJournal

Mixin for journal-based tables of vouchers.

Note that this is not explicitly marked as abstract by the application developer, but Lino knows that it is abstract because it has no model.

>>> ledger.ByJournal.abstract
False
>>> ledger.ByJournal.is_abstract()
True
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 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             (4100) Suppliers (Suppliers)                             (6040) Purchase of goods (Purchase of goods)                                   Purchase account (purchase_account)
 W       wages       Wages                 (4200) Employees (Employees)                             (6300) Wages (Wages)
 T       taxes       Taxes                 (4500) Tax Offices (Tax Offices)                         (4513) VAT declared (VAT declared)
 C       clearings   Clearings             (4800) Internal clearings (Internal clearings)
 B       bank_po     Bank payment orders   (4300) Pending Payment Orders (Pending Payment Orders)
======= =========== ===================== ======================================================== ============================================== =============================== =====================================
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

The demo database 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    (4100) Suppliers                Purchase invoices (PRC)
 4    (4000) Customers                Bestbank Payment Orders (PMO)
 5    (4100) Suppliers                Bestbank Payment Orders (PMO)
 6    (4500) Tax Offices              Bestbank Payment Orders (PMO)
 7    (6300) Wages                    Bestbank Payment Orders (PMO)
 8    (4000) Customers                Cash book (CSH)
 9    (4100) Suppliers                Cash book (CSH)
 10   (4500) Tax Offices              Cash book (CSH)
 11   (6300) Wages                    Cash book (CSH)
 12   (4300) Pending Payment Orders   Cash book (CSH)
 13   (4000) Customers                Bestbank (BNK)
 14   (4100) Suppliers                Bestbank (BNK)
 15   (4500) Tax Offices              Bestbank (BNK)
 16   (6300) Wages                    Bestbank (BNK)
 17   (4300) Pending Payment Orders   Bestbank (BNK)
 18   (4000) Customers                Miscellaneous transactions (MSC)
 19   (4100) Suppliers                Miscellaneous transactions (MSC)
 20   (4500) Tax Offices              Miscellaneous transactions (MSC)
 21   (6300) Wages                    Miscellaneous transactions (MSC)
 22   (4300) Pending Payment Orders   Miscellaneous transactions (MSC)
 23   (4000) Customers                Preliminary transactions (PRE)
 24   (4100) Suppliers                Preliminary transactions (PRE)
 25   (4500) Tax Offices              Preliminary transactions (PRE)
 26   (6300) Wages                    Preliminary transactions (PRE)
 27   (4300) Pending Payment Orders   Preliminary transactions (PRE)
 28   (4000) Customers                Paychecks (SAL)
 29   (4100) Suppliers                Paychecks (SAL)
 30   (4500) Tax Offices              Paychecks (SAL)
 31   (6300) Wages                    Paychecks (SAL)
 32   (4300) Pending Payment Orders   Paychecks (SAL)
 33   (4500) Tax Offices              VAT declarations (VAT)
==== =============================== ==================================

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
 (4100) Suppliers
 (4500) Tax Offices
 (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.

There can be debtors who are not customers. For example a tax office. A bank is a debtor when pending payment orders are booked to this account. A tax office is a debtor when we had more VAT deductible (sales) than VAT due (purchases).

>>> ses.show(ledger.Debtors, column_names="due_date partner partner_id balance")
... 
==================== ================================== ========== ===============
 Due date             Partner                            ID         Balance
-------------------- ---------------------------------- ---------- ---------------
 10/02/2014           Dubois Robin                       179        8 737,10
 04/02/2015           Mehrwertsteuer-Kontrollamt Eupen   192        12,71
 10/02/2015           Radermacher Edgard                 157        3 387,78
 13/02/2015           Bestbank                           100        69,63
 13/02/2015           Radermacher Guido                  159        268,62
 07/03/2015           Radermacher Hedi                   161        3 629,82
 09/03/2015           Radermacher Jean                   163        822,57
 10/03/2015           di Rupo Didier                     164        338,80
 11/03/2015           da Vinci David                     165        1 961,38
 **Total (9 rows)**                                      **1440**   **19 228,41**
==================== ================================== ========== ===============

The DebtsByPartner shows one row per uncleared invoice, and a list of --usually partial-- payments per invoice. This table is used for both debtors and creditors, which can be useful when you have business partners who are both customers and providers.

By convention, this list shows a debit balance as a negative number and a crediting balance as a positive number.

For example here is the detail of the debts for partner 165 from above list:

>>> obj = contacts.Partner.objects.get(pk=165)
>>> obj
Partner #165 ('da Vinci David')
>>> ses.show(ledger.DebtsByPartner, obj)
... 
==================== =============== ========================== ==========
 Due date             Balance         Debts                      Payments
-------------------- --------------- -------------------------- ----------
 11/03/2015           -647,35         `SLS 14/2015 <Detail>`__
 12/03/2015           -1 314,03       `SLS 15/2015 <Detail>`__
 **Total (2 rows)**   **-1 961,38**
==================== =============== ========================== ==========

Here is an example of a provider to whom we owe money:

>>> obj = contacts.Partner.objects.get(pk=101)
>>> obj
Partner #101 ('Rumma & Ko OÜ')
>>> ses.show(ledger.DebtsByPartner, obj)
... 
==================== ============ ======= ==========================
 Due date             Balance      Debts   Payments
-------------------- ------------ ------- --------------------------
 04/03/2015           141,60               `PRC 16/2015 <Detail>`__
 **Total (1 rows)**   **141,60**
==================== ============ ======= ==========================

Creditors are partners who gave us credit, IOW to whom we owe money. The most common creditors are providers, i.e. partners who sent 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       141,60
 Bäckerei Ausdemwald   102       608,20
 Bäckerei Mießen       103       1 214,40
 Bäckerei Schmitz      104       3 272,98
 Garage Mergelsberg    105       143,40
 Donderweer BV         106       204,40
 **Total (6 rows)**    **621**   **5 584,98**
===================== ========= ==============

(Currently not tested because the only example is a sales invoice for 101 in 2014-01 that is already paid. Need to adapt some fixture to get more cases) Partner 101 from above list is both a supplier and a customer: 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.

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

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
2014
>>> dd.today()
datetime.date(2015, 3, 12)
>>> dd.today().year + 5
2020
>>> rt.show(ledger.FiscalYears)
... 
=========== ============ ============ =======
 Reference   Start date   End date     State
----------- ------------ ------------ -------
 2014        01/01/2014   31/12/2014   Open
 2015        01/01/2015   31/12/2015   Open
 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
=========== ============ ============ =======

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
----------- ------------ ------------ ------------- ------- --------
 2014-01     01/01/2014   31/01/2014   2014          Open
 2014-02     01/02/2014   28/02/2014   2014          Open
 2014-03     01/03/2014   31/03/2014   2014          Open
 2014-04     01/04/2014   30/04/2014   2014          Open
 2014-05     01/05/2014   31/05/2014   2014          Open
 2014-06     01/06/2014   30/06/2014   2014          Open
 2014-07     01/07/2014   31/07/2014   2014          Open
 2014-08     01/08/2014   31/08/2014   2014          Open
 2014-09     01/09/2014   30/09/2014   2014          Open
 2014-10     01/10/2014   31/10/2014   2014          Open
 2014-11     01/11/2014   30/11/2014   2014          Open
 2014-12     01/12/2014   31/12/2014   2014          Open
 2015-01     01/01/2015   31/01/2015   2015          Open
 2015-02     01/02/2015   28/02/2015   2015          Open
 2015-03     01/03/2015   31/03/2015   2015          Open
 2015-12     01/12/2015   31/12/2015   2015          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".

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

The ledger plugin defines a list of voucher types, a choicelist that is populated by other plugins like lino_xl.lib.vat, lino_xl.lib.trading or lino_xl.lib.orders who define some subclass of Voucher and then must "register" that model to be used by one or several voucher types.

Every journal must have its voucher type, configured in the journal's voucher_type field. Several journals may share a same voucher type. The voucher type of a journal must not change as long as the journal has at least one voucher.

class lino_xl.lib.ledger.VoucherTypes

The list of voucher types available in this application.

Each item is an instances of VoucherType.

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).

In more complex cases the application developer can define more than one voucher type per model by providing alternative tables (views) for it.

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 having master_key set to the journal.

The states of a ledger voucher

class lino_xl.lib.ledger.VoucherState

Base class for items of VoucherStates.

is_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.

>>> rt.show(ledger.VoucherStates)
======= ============ ============ ==========
 value   name         text         Editable
------- ------------ ------------ ----------
 10      draft        Draft        Yes
 20      registered   Registered   No
 30      signed       Signed       No
 40      cancelled    Cancelled    No
======= ============ ============ ==========
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

The Cancelled state is similar to Draft, except that you cannot edit the fields. This is used e.g. for an invoice that has been sent, but the customer signaled that they don'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 any more. 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 ledger voucher that contains this item.

The related_name must be 'items'.

title

The heading of this voucher item.

Currently (because of Django ticket #19465), these fields are not defined by the mixin but must be defined by the implementing subclasses.

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.trading.Invoice, lino_xl.lib.finan.DocItem)

match

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

class lino_xl.lib.ledger.PaymentRelated

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.

payment_term

The payment term to apply for this transaction.

This is a pointer to PaymentTerm.

payment_method

The payment method to to apply for this transaction.

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.Payable

Model mixin for objects that represent a payable transaction.

your_ref

The reference used by the business partner for referring to this voucher.

due_date

The date when the invoice is expected to have been paid.

get_payable_sums_dict(self)

To be implemented by subclasses. Expected to return a dict which maps 4-tuples (acc_tuple, project, vat_class, vat_regime) to the payable amount. acc_tuple is itself a tuple (general_account, analytic_account), vat_class is a lino_xl.lib.vat.VatClasses choice and vat_regime a lino_xl.lib.vat.VatRegimes choice.

get_wanted_movements(self)

Implements lino_xl.lib.ledger.Voucher.get_wanted_movements().

class lino_xl.lib.ledger.PeriodRange

Model mixin for objects that cover a range of accounting periods.

start_period

The first period of the range to cover.

end_period

The last period of the range to cover.

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 covered.

get_period_filter(self, voucher_prefix, **kwargs)
class lino_xl.lib.ledger.PeriodRangeObservable

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

Class attribute:

observable_period_field = 'accounting_period'

The name of the database field on the observed model to use for filtering.

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, ...

Filtering partners regarding ledger movements

The ledger plugin adds a choice has_open_movements to the observed_events parameter field of the lino_xl.lib.contacts.Partners table.

Show only companies that have at least one open ledger movement:

>>> pv = dict(observed_event=rt.models.contacts.PartnerEvents.has_open_movements)
>>> rt.login("robin").show(contacts.Companies, param_values=pv)
... 
================================== ===================================================== ================ ======= ======== ===== ==========
 Name                               Address                                               e-mail address   Phone   Mobile   ID    Language
---------------------------------- ----------------------------------------------------- ---------------- ------- -------- ----- ----------
 Bestbank                                                                                                                   100
 Bäckerei Ausdemwald                Vervierser Straße 45, 4700 Eupen                                                        102
 Bäckerei Mießen                    Gospert 103, 4700 Eupen                                                                 103
 Bäckerei Schmitz                   Aachener Straße 53, 4700 Eupen                                                          104
 Donderweer BV                      Edisonstraat 12, 4816 AR Breda, Netherlands                                             106
 Garage Mergelsberg                 Hauptstraße 13, 4730 Raeren                                                             105
 Mehrwertsteuer-Kontrollamt Eupen   Vervierser Str. 8, 4700 Eupen                                                           192
 Rumma & Ko OÜ                      Uus tn 1, Vigala vald, 78003 Rapla maakond, Estonia                                     101
================================== ===================================================== ================ ======= ======== ===== ==========
>>> settings.SITE.the_demo_date
datetime.date(2015, 3, 12)
>>> pv['start_date'] = i2d(20141231)
>>> rt.login("robin").show(contacts.Companies, param_values=pv)
... 
================================== ===================================================== ================ ======= ======== ===== ==========
 Name                               Address                                               e-mail address   Phone   Mobile   ID    Language
---------------------------------- ----------------------------------------------------- ---------------- ------- -------- ----- ----------
 Bestbank                                                                                                                   100
 Bäckerei Ausdemwald                Vervierser Straße 45, 4700 Eupen                                                        102
 Bäckerei Mießen                    Gospert 103, 4700 Eupen                                                                 103
 Bäckerei Schmitz                   Aachener Straße 53, 4700 Eupen                                                          104
 Donderweer BV                      Edisonstraat 12, 4816 AR Breda, Netherlands                                             106
 Garage Mergelsberg                 Hauptstraße 13, 4730 Raeren                                                             105
 Mehrwertsteuer-Kontrollamt Eupen   Vervierser Str. 8, 4700 Eupen                                                           192
 Rumma & Ko OÜ                      Uus tn 1, Vigala vald, 78003 Rapla maakond, Estonia                                     101
================================== ===================================================== ================ ======= ======== ===== ==========
>>> pv['start_date'] = i2d(20151231)
>>> rt.login("robin").show(contacts.Companies, param_values=pv)
... 
No data to display

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=109)
>>> rt.show(ledger.MovementsByPartner, par, nosummary=True)
============ =============== ================================================== ============ ============ ============= =========
 Value date   Voucher         Description                                        Debit        Credit       Match         Cleared
------------ --------------- -------------------------------------------------- ------------ ------------ ------------- ---------
 21/03/2014   *BNK 3/2014*    *(4000) Customers* | *Bernd Brechts Bücherladen*                320,00       SLS 10/2014   Yes
 07/03/2014   *SLS 10/2014*   *(4000) Customers*                                 320,00                    SLS 10/2014   Yes
                              **Balance 0.00 (2 movements)**                     **320,00**   **320,00**
============ =============== ================================================== ============ ============ ============= =========
>>> mt = contenttypes.ContentType.objects.get_for_model(par.__class__).pk
>>> url = "api/ledger/MovementsByPartner?fmt=json&mk={}&mt={}".format(par.pk, mt)
>>> cols = 'count rows no_data_text success title param_values'
>>> demo_get('robin', url + "&sort=credit&dir=ASC", cols, 2)

The following failed before 20181016:

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

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.

The reregister admin command

In certain exceptional situations you may want to rebuild all the ledger movements on your site. For example after the changes on 2020-10-15 (see 2020). Or when you have changed something in your site configuration so that certain movements would go to other accounts than before (and want to apply this change to all registered vouchers).

The reregister admin command re-registers all ledger vouchers.

reregister

Re-register all ledger vouchers.

If no arguments are given, run it on all vouchers. Otherwise every positional argument is expected to be the ref of a journal, and are being re-registered.

When called with no arguments, all movements are deleted from the database. This can help if the database contains movments with invalid voucher pointer.

Example run:

>>> from atelier.sheller import Sheller
>>> shell = Sheller(settings.SITE.project_dir.parent)
>>> shell('python manage.py reregister --noinput')
... 
Re-register all vouchers in journal Verkaufsrechnungen (SLS)
Re-register all vouchers in journal Gutschriften Verkauf (SLC)
Re-register all vouchers in journal Einkaufsrechnungen (PRC)
Re-register all vouchers in journal Zahlungsaufträge (PMO)
Re-register all vouchers in journal Kassenbuch (CSH)
Re-register all vouchers in journal Bestbank (BNK)
Re-register all vouchers in journal Diverse Buchungen (MSC)
Re-register all vouchers in journal Preliminary transactions (PRE)
Re-register all vouchers in journal Lohnscheine (SAL)
Re-register all vouchers in journal MwSt.-Erklärungen (VAT)
220 vouchers have been re-registered.
Check clearings for all partners