Debts mediation

The lino_welfare.modlib.debts modules adds functionality for doing debts mediation.

One job of a debts mediator is to make a debts mediation budget for their client.

A tested document

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

>>> import lino
>>> lino.startup('lino_welfare.projects.gerd.settings.doctests')
>>> from lino.api.doctest import *
>>> ses = rt.login('robin')

Overview

debts mediation budget

A document that describes the financial situation of a person or household at a given moment.

Database model: Budget

Budgets

The demo database has 17 budgets with fictive generated data:

>>> debts.Budget.objects.count()
17

For the following examples we will use budget no. 3:

>>> translation.activate('en')
>>> obj = debts.Budget.objects.get(pk=3)
>>> print(str(obj))
Budget 3 for Jérôme & Theresia Jeanémart-Thelen

Actors

This budget has 3 actors:

>>> len(obj.get_actors())
3

Every actor is an instance of Actor, which is designed to be used in templates. For example, every actor has four attributes header, person, client and household:

>>> u = attrtable(obj.get_actors(), 'header person client household')
>>> print(u)
======== ===================== ======================== ========================================================
 header   person                client                   household
-------- --------------------- ------------------------ --------------------------------------------------------
 Common   None                  None                     Jérôme & Theresia Jeanémart-Thelen (Factual household)
 Herr     Mr Jérôme JEANÉMART   JEANÉMART Jérôme (181)   None
 Frau     Mrs Theresia THELEN   None                     None
======== ===================== ======================== ========================================================

Data entry panels

Here is the textual representation of the “Expenses” panel:

>>> ses.show(debts.ExpensesByBudget, obj,
...   column_names="account description amount remark",
...   limit=10)
... 
============================= =============================== ============ ===========
 Account                       Description                     Amount       Remark
----------------------------- ------------------------------- ------------ -----------
 (3010) Rent                   Miete                           41,00
 (3011) Water                  Wasser                          47,00
 (3012) Electricity            Strom
 (3020) Telephone & Internet   Festnetz-Telefon und Internet   5,00
 (3021) Cell phone             Handy                           10,00
 (3030) Transport costs        Fahrtkosten                     15,00        Kino
 (3030) Transport costs        Fahrtkosten                     15,00        Einkaufen
 (3031) Public transport       TEC Busabonnement               20,00
 (3032) Fuel                   Benzin                          26,00
 (3033) Car maintenance        Unterhalt Auto                  31,00
 **Total (35 rows)**                                           **210,00**
============================= =============================== ============ ===========

Note that the above table contains a mixture of German and English texts because our current language is German while the partner speaks English:

>>> print(obj.partner.language)

Description and Remark have been entererd for this particular Budget instance and are therefore in the partner’s language. Everything else depends on the current user language.

The summary panel

Here are some more slave tables.

>>> ses.show(debts.ResultByBudget, obj)
=================================================== ==============
 Description                                         Amount
--------------------------------------------------- --------------
 Monthly incomes                                     5 000,00
 Monthly expenses                                    -565,00
 Monthly reserve for yearly expenses (236,00 / 12)   -19,67
 Monthly installment for running credits             -45,00
 **Remaining for credits and debts**                 **4 370,33**
=================================================== ==============
>>> obj.include_yearly_incomes = True
>>> ses.show(debts.ResultByBudget, obj)
=================================================== ==============
 Description                                         Amount
--------------------------------------------------- --------------
 Monthly incomes                                     5 000,00
 Yearly incomes (2 400,00 / 12)                      200,00
 Monthly expenses                                    -565,00
 Monthly reserve for yearly expenses (236,00 / 12)   -19,67
 Monthly installment for running credits             -45,00
 **Remaining for credits and debts**                 **4 570,33**
=================================================== ==============
>>> ses.show(debts.DebtsByBudget, obj)
================================= ==============
 Description                       Amount
--------------------------------- --------------
 Loans                             300,00
 Debts                             600,00
 Invoices to pay (distributable)   900,00
 Bailiff (distributable)           1 200,00
 Cash agency (distributable)       1 500,00
 **Liabilities**                   **4 500,00**
================================= ==============
>>> ses.show(debts.DebtsByBudget, obj, language="de")
================================== ==============
 Beschreibung                       Betrag
---------------------------------- --------------
 Kredite                            300,00
 Schulden                           600,00
 Zahlungsrückstände (verteilbar)    900,00
 Gerichtsvollzieher (verteilbar)    1 200,00
 Inkasso-Unternehmen (verteilbar)   1 500,00
 **Verpflichtungen**                **4 500,00**
================================== ==============
>>> ses.show(debts.DistByBudget, obj, language="de")
====================== ===================== ============== ============ ====================================
 Kreditor               Beschreibung          Schuld         %            Betrag der monatlichen Rückzahlung
---------------------- --------------------- -------------- ------------ ------------------------------------
 Auto École Verte       Zahlungsrückstände    900,00         25,00        30,00
 ÖSHZ Kettenis          Gerichtsvollzieher    1 200,00       33,33        40,00
 BISA                   Inkasso-Unternehmen   1 500,00       41,67        50,00
 **Total (3 Zeilen)**                         **3 600,00**   **100,00**   **120,00**
====================== ===================== ============== ============ ====================================

The printed document

The following table shows how Lino renders remarks in the printed version: they are added to the description between parentheses (e.g. “Spare time”), and if several entries were grouped into a same printable row (e.g. “Fahrtkosten”), they are separated by commas.

>>> groups = list(obj.entry_groups(ses))
>>> ses.show(groups[0].action_request)
... 
==================== ========= ======== ====== ============== ==============
 Description          Remarks   Common   Herr   Frau           Total
-------------------- --------- -------- ------ -------------- --------------
 Gehälter                                       800,00         800,00
 Renten                                         1 000,00       1 000,00
 Integrationszulage                             1 200,00       1 200,00
 Ersatzeinkünfte                                1 400,00       1 400,00
 Alimente
 Essen-Schecks                                  200,00         200,00
 Andere                                         400,00         400,00
 **Total (7 rows)**                             **5 000,00**   **5 000,00**
==================== ========= ======== ====== ============== ==============
>>> ses.show(groups[1].action_request, language="de")
... 
================================== ================= =============== ============ ====== ====== ============
 Beschreibung                       Bemerkungen       Jährl. Betrag   Gemeinsam    Herr   Frau   Total
---------------------------------- ----------------- --------------- ------------ ------ ------ ------------
 Miete                                                492,00          41,00                      41,00
 Wasser                                               564,00          47,00                      47,00
 Strom
 Festnetz-Telefon und Internet                        60,00           5,00                       5,00
 Handy                                                120,00          10,00                      10,00
 Fahrtkosten                        Kino, Einkaufen   360,00          30,00                      30,00
 TEC Busabonnement                                    240,00          20,00                      20,00
 Benzin                                               312,00          26,00                      26,00
 Unterhalt Auto                                       372,00          31,00                      31,00
 Schulkosten                                          432,00          36,00                      36,00
 Tagesmutter & Kleinkindbetreuung                     492,00          41,00                      41,00
 Gesundheit                                           564,00          47,00                      47,00
 Kleidung
 Ernährung                                            60,00           5,00                       5,00
 Hygiene                                              120,00          10,00                      10,00
 Krankenkassenbeiträge                                180,00          15,00                      15,00
 Gewerkschaftsbeiträge                                240,00          20,00                      20,00
 Unterhaltszahlungen                                  312,00          26,00                      26,00
 Pensionssparen                                       372,00          31,00                      31,00
 Tabak                                                432,00          36,00                      36,00
 Freizeit & Unterhaltung            Seminar           492,00          41,00                      41,00
 Haustiere                                            564,00          47,00                      47,00
 Sonstige
 **Total (23 Zeilen)**                                **6 780,00**    **565,00**                 **565,00**
================================== ================= =============== ============ ====== ====== ============
>>> ses.show(groups[2].action_request, language="de")
... 
==================================== =========== ====== ============ ============
 Beschreibung                         Gemeinsam   Herr   Frau         Total
------------------------------------ ----------- ------ ------------ ------------
 Urlaubsgeld (600.00 / 12)                               50,00        50,00
 Jahresendzulage (800.00 / 12)                           66,67        66,67
 Gewerkschaftsprämie (1000.00 / 12)                      83,33        83,33
 **Total (3 Zeilen)**                                    **200,00**   **200,00**
==================================== =========== ====== ============ ============

Something in French

>>> ses.show(debts.DistByBudget, obj, language="fr")
====================== ===================== ============== ============ =======================
 Créancier              Description           Dette          %            Remboursement mensuel
---------------------- --------------------- -------------- ------------ -----------------------
 Auto École Verte       Zahlungsrückstände    900,00         25,00        30,00
 ÖSHZ Kettenis          Gerichtsvollzieher    1 200,00       33,33        40,00
 BISA                   Inkasso-Unternehmen   1 500,00       41,67        50,00
 **Total (3 lignes)**                         **3 600,00**   **100,00**   **120,00**
====================== ===================== ============== ============ =======================

Or the same in English:

>>> with translation.override('en'):
...     ses.show(debts.DistByBudget, obj)
==================== ===================== ============== ============ ===========================
 Creditor             Description           Debt           %            Monthly payback suggested
-------------------- --------------------- -------------- ------------ ---------------------------
 Auto École Verte     Zahlungsrückstände    900,00         25,00        30,00
 ÖSHZ Kettenis        Gerichtsvollzieher    1 200,00       33,33        40,00
 BISA                 Inkasso-Unternehmen   1 500,00       41,67        50,00
 **Total (3 rows)**                         **3 600,00**   **100,00**   **120,00**
==================== ===================== ============== ============ ===========================

Note that the Description still shows German words because these are stored per Budget, and Budget #3 is addressed to a German-speaking partner.

A web request

The following snippet reproduces a one-day bug discovered 2013-05-27:

>>> url = '/api/debts/Budgets/3?fmt=json&an=detail'
>>> test_client.force_login(rt.login('rolf').user)
>>> res = test_client.get(url,REMOTE_USER='rolf')
>>> print(res.status_code)
200
>>> result = json.loads(res.content)
>>> print(' '.join(sorted(result.keys())))
data disable_delete id navinfo param_values title

Editability of tables

The following is to check whether the editable attribute inherited correctly.

>>> debts.Budgets.editable
True
>>> debts.EntriesByBudget.editable
True
>>> debts.DistByBudget.editable
False
>>> debts.LiabilitiesByBudget.editable
True
>>> debts.PrintEntriesByBudget.editable
False

The stories

Here is now (almost) the whole content of a printed budget.

>>> obj = debts.Budget.objects.get(pk=4)
>>> ses.story2rst(obj.data_story(ses))
... 
~~~~~~~~~~~~~~~~~~~~
Monatliche Einkünfte
~~~~~~~~~~~~~~~~~~~~

====================== ============= =========== ====== ============== ==============
 Beschreibung           Bemerkungen   Gemeinsam   Herr   Frau           Total
---------------------- ------------- ----------- ------ -------------- --------------
 Gehälter                                                1 200,00       1 200,00
 Renten                                                  1 400,00       1 400,00
 Integrationszulage
 Ersatzeinkünfte                                         200,00         200,00
 Alimente                                                400,00         400,00
 Essen-Schecks                                           600,00         600,00
 Andere                                                  800,00         800,00
 **Total (7 Zeilen)**                                    **4 600,00**   **4 600,00**
====================== ============= =========== ====== ============== ==============

~~~~~~~~~~~~~~~~~~~
Monatliche Ausgaben
~~~~~~~~~~~~~~~~~~~

================================== ================= =============== ============ ====== ====== ============
 Beschreibung                       Bemerkungen       Jährl. Betrag   Gemeinsam    Herr   Frau   Total
---------------------------------- ----------------- --------------- ------------ ------ ------ ------------
 Miete                                                120,00          10,00                      10,00
 Wasser                                               180,00          15,00                      15,00
 Strom                                                240,00          20,00                      20,00
 Festnetz-Telefon und Internet                        312,00          26,00                      26,00
 Handy                                                372,00          31,00                      31,00
 Fahrtkosten                        Einkaufen, Kino   864,00          72,00                      72,00
 TEC Busabonnement                                    492,00          41,00                      41,00
 Benzin                                               564,00          47,00                      47,00
 Unterhalt Auto
 Schulkosten                                          60,00           5,00                       5,00
 Tagesmutter & Kleinkindbetreuung                     120,00          10,00                      10,00
 Gesundheit                                           180,00          15,00                      15,00
 Kleidung                                             240,00          20,00                      20,00
 Ernährung                                            312,00          26,00                      26,00
 Hygiene                                              372,00          31,00                      31,00
 Krankenkassenbeiträge                                432,00          36,00                      36,00
 Gewerkschaftsbeiträge                                492,00          41,00                      41,00
 Unterhaltszahlungen                                  564,00          47,00                      47,00
 Pensionssparen
 Tabak                                                60,00           5,00                       5,00
 Freizeit & Unterhaltung            Kino              120,00          10,00                      10,00
 Haustiere                                            180,00          15,00                      15,00
 Sonstige                                             240,00          20,00                      20,00
 **Total (23 Zeilen)**                                **6 516,00**    **543,00**                 **543,00**
================================== ================= =============== ============ ====== ====== ============

~~~~~~~~~~~~~~~~~~~
Jährliche Einkünfte
~~~~~~~~~~~~~~~~~~~

==================================== =========== ====== ============ ============
 Beschreibung                         Gemeinsam   Herr   Frau         Total
------------------------------------ ----------- ------ ------------ ------------
 Urlaubsgeld (1000.00 / 12)                              83,33        83,33
 Jahresendzulage (1200.00 / 12)                          100,00       100,00
 Gewerkschaftsprämie (1400.00 / 12)                      116,67       116,67
 **Total (3 Zeilen)**                                    **300,00**   **300,00**
==================================== =========== ====== ============ ============

~~~~~~~
Steuern
~~~~~~~

====================== ============= =============== =========== ====== ====== ===========
 Beschreibung           Bemerkungen   Jährl. Betrag   Gemeinsam   Herr   Frau   Total
---------------------- ------------- --------------- ----------- ------ ------ -----------
 Gemeindesteuer                       26,00           2,17                      2,17
 Kanalisationssteuer                  31,00           2,58                      2,58
 Müllsteuer                           36,00           3,00                      3,00
 Autosteuer                           41,00           3,42                      3,42
 Immobiliensteuer                     47,00           3,92                      3,92
 Andere
 **Total (6 Zeilen)**                 **181,00**      **15,08**                 **15,08**
====================== ============= =============== =========== ====== ====== ===========

~~~~~~~~~~~~~~
Versicherungen
~~~~~~~~~~~~~~

======================= ============= =============== =========== ====== ====== ==========
 Beschreibung            Bemerkungen   Jährl. Betrag   Gemeinsam   Herr   Frau   Total
----------------------- ------------- --------------- ----------- ------ ------ ----------
 Feuer                                 5,00            0,42                      0,42
 Familienhaftpflicht                   10,00           0,83                      0,83
 Auto                                  15,00           1,25                      1,25
 Lebensversicherung                    20,00           1,67                      1,67
 Andere Versicherungen                 26,00           2,17                      2,17
 **Total (5 Zeilen)**                  **76,00**       **6,33**                  **6,33**
======================= ============= =============== =========== ====== ====== ==========

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Schulden, Zahlungsrückstände, Kredite
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

====================== ============= ============ ============ ====== ====== ============
 Partner                Bemerkungen   Monatsrate   Gemeinsam    Herr   Frau   Total
---------------------- ------------- ------------ ------------ ------ ------ ------------
 Pro Aktiv V.o.G.                                  900,00                     900,00
 **Total (1 Zeilen)**                              **900,00**                 **900,00**
====================== ============= ============ ============ ====== ====== ============

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Gerichtsvollzieher und Inkasso
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

====================== ========================== ============= ============ =========== ============== ============== ==============
 Schuldeneintreiber     Partner                    Bemerkungen   Monatsrate   Gemeinsam   Herr           Frau           Total
---------------------- -------------------------- ------------- ------------ ----------- -------------- -------------- --------------
 Cashback sprl          Werkstatt Cardijn V.o.G.                                          1 200,00                      1 200,00
 Money Wizard AS        Behindertenstätten Eupen                                                         1 500,00       1 500,00
 **Total (2 Zeilen)**                                                                     **1 200,00**   **1 500,00**   **2 700,00**
====================== ========================== ============= ============ =========== ============== ============== ==============
>>> ses.story2rst(obj.summary_story(ses))
... 
--------------------
Einnahmen & Ausgaben
--------------------

========================================================= ==============
 Beschreibung                                              Betrag
--------------------------------------------------------- --------------
 Monatliche Einkünfte                                      4 600,00
 Monatliche Ausgaben                                       -543,00
 Monatliche Reserve für jährliche Ausgaben (257,00 / 12)   -21,42
 **Restbetrag für Kredite und Zahlungsrückstände**         **4 035,58**
========================================================= ==============

---------------
Verpflichtungen
---------------

================================== ==============
 Beschreibung                       Betrag
---------------------------------- --------------
 Zahlungsrückstände (verteilbar)    900,00
 Gerichtsvollzieher (verteilbar)    1 200,00
 Inkasso-Unternehmen (verteilbar)   1 500,00
 **Verpflichtungen**                **3 600,00**
================================== ==============

------------------
Schuldenverteilung
------------------

========================== ===================== ============== ============ ====================================
 Kreditor                   Beschreibung          Schuld         %            Betrag der monatlichen Rückzahlung
-------------------------- --------------------- -------------- ------------ ------------------------------------
 Pro Aktiv V.o.G.           Zahlungsrückstände    900,00         25,00        30,00
 Werkstatt Cardijn V.o.G.   Gerichtsvollzieher    1 200,00       33,33        40,00
 Behindertenstätten Eupen   Inkasso-Unternehmen   1 500,00       41,67        50,00
 **Total (3 Zeilen)**                             **3 600,00**   **100,00**   **120,00**
========================== ===================== ============== ============ ====================================

Filtering budgets

The Explorer ‣ Debt mediation ‣ Budgets nenu command shows the table of all budgets.

>>> kwargs = dict(column_names="id user date partner dist_amount")
>>> ses.show(debts.Budgets, **kwargs)
==== ================== ========== ================================================= =====================
 ID   Autor              Datum      Partner                                           Verteilbarer Betrag
---- ------------------ ---------- ------------------------------------------------- ---------------------
 1    Kerstin Kerres     21.06.14   Gerd & Tatjana Gerkens-Kasennova                  120,00
 2    Patrick Paraneau   20.06.14   Hubert & Judith Huppertz-Jousten                  120,00
 3    Romain Raffault    19.06.14   Jérôme & Theresia Jeanémart-Thelen                120,00
 4    Rolf Rompen        18.06.14   Denis & Mélanie Denon-Mélard                      120,00
 5    Robin Rood         17.06.14   Robin & Lisa Dubois-Lahm                          120,00
 6    Kerstin Kerres     16.06.14   Jérôme & Marie-Louise Jeanémart-Vandenmeulenbos   120,00
 7    Patrick Paraneau   15.06.14   Hubert & Gaby Frisch-Frogemuth                    120,00
 8    Romain Raffault    14.06.14   Paul & Paula Frisch-Einzig                        120,00
 9    Rolf Rompen        13.06.14   Paul & Petra Frisch-Zweith                        120,00
 10   Robin Rood         12.06.14   Ludwig & Laura Frisch-Loslever                    120,00
 11   Kerstin Kerres     11.06.14   Albert & Eveline Adam-Evrard                      120,00
 12   Patrick Paraneau   10.06.14   Albert & Françoise Adam-Freisen                   120,00
 13   Romain Raffault    09.06.14   Bruno & Eveline Braun-Evrard                      120,00
 14   Rolf Rompen        08.06.14   Bruno & Françoise Braun-Freisen                   120,00
 15   Robin Rood         07.06.14   Ausdemwald Alfons                                 120,00
 16   Kerstin Kerres     06.06.14   Collard Charlotte                                 120,00
 17   Patrick Paraneau   05.06.14   Dobbelstein Dorothée                              120,00
                                                                                      **2 040,00**
==== ================== ========== ================================================= =====================

The menu command Debts mediation ‣ My budgets shows the budgets authored by the requesting user.

>>> ses.show(debts.MyBudgets, **kwargs)
==== ============ ========== ================================ =====================
 ID   Autor        Datum      Partner                          Verteilbarer Betrag
---- ------------ ---------- -------------------------------- ---------------------
 5    Robin Rood   17.06.14   Robin & Lisa Dubois-Lahm         120,00
 10   Robin Rood   12.06.14   Ludwig & Laura Frisch-Loslever   120,00
 15   Robin Rood   07.06.14   Ausdemwald Alfons                120,00
                                                               **360,00**
==== ============ ========== ================================ =====================

In order to see the budgets issued by other users, users can manually select that other user in the filter parameter “Author”.

>>> pv = dict(user=users.User.objects.get(username='kerstin'))
>>> kwargs.update(param_values=pv)
>>> ses.show(debts.Budgets, **kwargs)
==== ================ ========== ================================================= =====================
 ID   Autor            Datum      Partner                                           Verteilbarer Betrag
---- ---------------- ---------- ------------------------------------------------- ---------------------
 1    Kerstin Kerres   21.06.14   Gerd & Tatjana Gerkens-Kasennova                  120,00
 6    Kerstin Kerres   16.06.14   Jérôme & Marie-Louise Jeanémart-Vandenmeulenbos   120,00
 11   Kerstin Kerres   11.06.14   Albert & Eveline Adam-Evrard                      120,00
 16   Kerstin Kerres   06.06.14   Collard Charlotte                                 120,00
                                                                                    **480,00**
==== ================ ========== ================================================= =====================

The first meeting of a budget

>>> translation.activate('en')

The following shows how we use the lino_welfare.modlib.debts.Actor.get_first_meeting() method for printing the date and user of the first meeting.

Here is a list of all actors for which there is a first meeting.

>>> msg = "Budget {0} : First meeting on {1} with user {2}"
>>> for actor in debts.Actor.objects.all():
...     n = actor.get_first_meeting()
...     if n is not None:
...         print(msg.format(actor.budget.id, dd.fdl(n.date), n.user))
Budget 1 : First meeting on 21 June 2014 with user Kerstin Kerres
Budget 3 : First meeting on 19 June 2014 with user Romain Raffault
Budget 4 : First meeting on 18 June 2014 with user Rolf Rompen
Budget 5 : First meeting on 17 June 2014 with user Robin Rood
Budget 5 : First meeting on 17 June 2014 with user Robin Rood
Budget 6 : First meeting on 16 June 2014 with user Kerstin Kerres
Budget 6 : First meeting on 16 June 2014 with user Kerstin Kerres

The syntax of appy.pod templates does not yet have a with statement.

The Default.odt template uses this in a construct similar to the following snippet:

>>> budget = debts.Budget.objects.get(pk=4)
>>> for actor in budget.get_actors():
...     print(actor.get_first_meeting_text())
None
First meeting on 18 June 2014 with Rolf Rompen
None

Models

class lino_welfare.modlib.debts.Account

An account is an item of an account chart used to collect ledger transactions or other accountable items.

name

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

group

The account group to which this account belongs. This must point to an instance of Group.

seqno

The sequence number of this account within its group.

ref

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

type

The account type of this account. This must point to an item of lino_welfare.modlib.debts.AccountTypes.

class lino_welfare.modlib.debts.Budget

Django model used to represent a debts mediation budget.

entry_groups(self, ar, types=None, **kw)

Yield the entry groups for this budget, i.e. one item for each account group for which this budget has some data.

Types

an optional string specifying a set of one-letter account type names. See AccountTypes.

Each entry group is encapsulated as a volatile helper object lino_welfare.modlib.debts.ui.EntryGroup.

class lino_welfare.modlib.debts.Actor

An actor of a budget is a partner who is part of the household for which the budget has been established.

class lino_welfare.modlib.debts.Entry

A detail row of a Budget.

budget

The Budget who contains this entry.

amount

The amount of money. An empty amount is different from a zero amount in that the latter will be printed while the former not.

account

The related Account.