Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More

cosi2 : A Lino Così for Belgium (FR)

This page contains code snippets (lines starting with >>>), which are being tested during our development workflow. The following snippet initializes the demo project used throughout this page.

>>> from lino_book.projects.cosi2.startup import *
>>> ses = rt.login('robin')

Used in miscellaneous tested documents, e.g.

Miscellaneous

Because with_assets is False for cosi2, lino_xl.lib.trading.InvoiceItem.asset is a dummy field, which we can see by testing whether field is None.

>>> settings.SITE.with_assets
False
>>> print(rt.models.trading.InvoiceItem.asset.field)
None

Slave tables with more than 15 rows

When you look at the detail window of Belgium in Lino Così then you see a list of all places in Belgium. This demo database contains exactly 48 entries:

>>> be = countries.Country.objects.get(isocode="BE")
>>> be.place_set.count()
48
>>> countries.PlacesByCountry.create_request(be).get_total_count()
48
>>> test_client.force_login(rt.login('robin').user)
>>> url = '/api/countries/PlacesByCountry?fmt=json&start=0&mt=5&mk=BE'
>>> res = test_client.get(url, REMOTE_USER='robin')
>>> print(res.status_code)
200
>>> result = json.loads(res.content.decode('utf-8'))
>>> print(len(result['rows']))
15

The 15 is because Lino has a hard-coded default value of returning only 15 rows when no limit has been specified.

In versions after 2013-09-03 you can change that limit for a given table by overriding the preview_limit parameter of your table definition. Or you can change it globally for all your tables by setting the preview_limit Site attribute to either None or some bigger value.

This parameter existed before but wasn’t tested. In your code this would simply look like this:

class PlacesByCountry(Places):
    preview_limit = 30

Here we override it on the living object:

>>> countries.PlacesByCountry.preview_limit = 25

Same request returns now 25 data rows:

>>> res = test_client.get(url, REMOTE_USER='robin')
>>> result = json.loads(res.content.decode('utf-8'))
>>> print(len(result['rows']))
25

To remove the limit altogether, you can say:

>>> countries.PlacesByCountry.preview_limit = None

and the same request now returns all 49 data rows:

>>> res = test_client.get(url,REMOTE_USER='robin')
>>> result = json.loads(res.content.decode('utf-8'))
>>> print(len(result['rows']))
49

Invoices to emit

The cosi2 demo project showcases an approach used e.g. in petrol stations where customers pay upon delivery when they fill their tank, they want to have a single invoice at the end of the month where every delivery is mentioned, and the station is legally required to book their purchases and sales of petrol every day. Some customers have the privilege of needing to pay only at the end of the month when they receive the invoice.

Lino helps to manage this kind of situations by using an accounting concept called factures à établir. The site owner writes a single daily invoice to a fictive customer “Invoices to emit”. This daily invoice causes VAT to get booked and the daily turnover to sync with sales and purchases. At the end of the month we then send the actual invoices to the customers. These invoices don’t report about our business activity, they are only informative, we call them “informal”, they list the deliveries of the last month and just book the total turnover from “Invoices to emit” to the real customer.

Payment term A means: this is just an informative invoice and the customer has already paid upon delivery.

>>> obj = rt.models.trading.VatProductInvoice.objects.filter(payment_term__ref="A").first()
>>> obj
VatProductInvoice #198 ('SLS 9/2023')
>>> rt.show(accounting.MovementsByVoucher, obj)
================== ================= ============ ============ ================ =========
 Account            Partner           Debit        Credit       Match            Cleared
------------------ ----------------- ------------ ------------ ---------------- ---------
 (4000) Customers   Hans Flott & Co   815,96                    **SLS 9/2023**   Yes
 (4000) Customers   Hans Flott & Co                815,96       **SLS 9/2023**   Yes
                                      **815,96**   **815,96**
================== ================= ============ ============ ================ =========

Payment terms B means: this is just an informative invoice regarding VAT, but the customer still has to pay.

>>> obj = rt.models.trading.VatProductInvoice.objects.filter(payment_term__ref="B").first()
>>> obj
VatProductInvoice #199 ('SLS 10/2023')
>>> obj.payment_term.informal
True
>>> obj.payment_term.payer
Company #83 ('Invoices to emit')
>>> rt.show(accounting.MovementsByVoucher, obj)
=========================== =========================== ============ ============ ================= =========
 Account                     Partner                     Debit        Credit       Match             Cleared
--------------------------- --------------------------- ------------ ------------ ----------------- ---------
 (4000) Customers            Bernd Brechts Bücherladen   320,00                    **SLS 10/2023**   No
 (4800) Internal clearings   Invoices to emit                         320,00       **SLS 10/2023**   No
                                                         **320,00**   **320,00**
=========================== =========================== ============ ============ ================= =========

The customer “Invoices to emit” is used to record internal clearing of invoices that have been paid at delivery. TODO: add monthly transaction in the demo fixture to balance the invoices to emit.

>>> obj = contacts.Company.objects.get(name="Invoices to emit")
>>> obj
Company #83 ('Invoices to emit')
>>> rt.show(accounting.MovementsByPartner, obj, display_mode="grid")
============ ===================== ================================================================================================== ======= ============== ============= =========
 Value date   Voucher               Description                                                                                        Debit   Credit         Match         Cleared
------------ --------------------- -------------------------------------------------------------------------------------------------- ------- -------------- ------------- ---------
 11/02/2025   `SLS 11/2025 <…>`__   `(4800) Internal clearings <…>`__ | `Adriencense Alexine <…>`__ | `Invoices to emit <…>`__                 780,45         SLS 11/2025   No
 14/12/2024   `SLS 57/2024 <…>`__   `(4800) Internal clearings <…>`__ | `Bernd Brechts Bücherladen <…>`__ | `Invoices to emit <…>`__           740,00         SLS 57/2024   No
 10/07/2024   `SLS 29/2024 <…>`__   `(4800) Internal clearings <…>`__ | `Boulanger Abdul Azeez <…>`__ | `Invoices to emit <…>`__               338,68         SLS 29/2024   No
 10/04/2024   `SLS 19/2024 <…>`__   `(4800) Internal clearings <…>`__ | `Booghmans Philomène <…>`__ | `Invoices to emit <…>`__                 387,20         SLS 19/2024   No
 13/02/2024   `SLS 8/2024 <…>`__    `(4800) Internal clearings <…>`__ | `Blondeel Théophile <…>`__ | `Invoices to emit <…>`__                  895,40         SLS 8/2024    No
 07/12/2023   `SLS 54/2023 <…>`__   `(4800) Internal clearings <…>`__ | `Bauwens Isabeau <…>`__ | `Invoices to emit <…>`__                     931,70         SLS 54/2023   No
 07/10/2023   `SLS 43/2023 <…>`__   `(4800) Internal clearings <…>`__ | `Arimont Gaston <…>`__ | `Invoices to emit <…>`__                      726,00         SLS 43/2023   No
 09/07/2023   `SLS 32/2023 <…>`__   `(4800) Internal clearings <…>`__ | `Alloo Béranger <…>`__ | `Invoices to emit <…>`__                      810,70         SLS 32/2023   No
 09/05/2023   `SLS 21/2023 <…>`__   `(4800) Internal clearings <…>`__ | `Adriencense Alexine <…>`__ | `Invoices to emit <…>`__                 1 197,90       SLS 21/2023   No
 07/03/2023   `SLS 10/2023 <…>`__   `(4800) Internal clearings <…>`__ | `Bernd Brechts Bücherladen <…>`__ | `Invoices to emit <…>`__           320,00         SLS 10/2023   No
                                    **Balance -7128.03 (10 movements)**                                                                        **7 128,03**
============ ===================== ================================================================================================== ======= ============== ============= =========