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
Person #16 is not a Partner¶
Person #16 (‘Altenberg Hans’) is not a Partner (master_key is <django.db.models.fields.related.ForeignKey: partner>)
>>> url = '/bs3/contacts/Person/16'
>>> test_client.force_login(rt.login('robin').user)
>>> res = test_client.get(url, REMOTE_USER='robin')
>>> print(res.status_code)
200
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
>>> 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 #9 ('SLS 9/2016')
>>> rt.show(accounting.MovementsByVoucher, obj)
================== =========================== ============ ============ ================ =========
Account Partner Debit Credit Match Cleared
------------------ --------------------------- ------------ ------------ ---------------- ---------
(4000) Customers Bernd Brechts Bücherladen 815,96 **SLS 9/2016** Yes
(4000) Customers Bernd Brechts Bücherladen 815,96 **SLS 9/2016** 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 #10 ('SLS 10/2016')
>>> obj.payment_term.informal
True
>>> obj.payment_term.payer
Company #82 ('Invoices to emit')
>>> rt.show(accounting.MovementsByVoucher, obj)
=========================== ====================== ============ ============ ================= =========
Account Partner Debit Credit Match Cleared
--------------------------- ---------------------- ------------ ------------ ----------------- ---------
(4000) Customers Reinhards Baumschule 320,00 **SLS 10/2016** No
(4800) Internal clearings Invoices to emit 320,00 **SLS 10/2016** 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 to balance the invoices to emit.
>>> obj = contacts.Company.objects.get(name="Invoices to emit")
>>> obj
Company #82 ('Invoices to emit')
>>> rt.show(accounting.MovementsByPartner, obj, display_mode="grid")
============ ===================== ============================================================================================= ======= ============== ============= =========
Value date Voucher Description Debit Credit Match Cleared
------------ --------------------- --------------------------------------------------------------------------------------------- ------- -------------- ------------- ---------
13/02/2017 `SLS 8/2017 <…>`__ `(4800) Internal clearings <…>`__ | `Blondeeuw Tristan <…>`__ | `Invoices to emit <…>`__ 740,00 SLS 8/2017 No
07/12/2016 `SLS 54/2016 <…>`__ `(4800) Internal clearings <…>`__ | `Beauve Marius <…>`__ | `Invoices to emit <…>`__ 770,00 SLS 54/2016 No
07/10/2016 `SLS 43/2016 <…>`__ `(4800) Internal clearings <…>`__ | `Arquin Geoffroy <…>`__ | `Invoices to emit <…>`__ 600,00 SLS 43/2016 No
09/07/2016 `SLS 32/2016 <…>`__ `(4800) Internal clearings <…>`__ | `Alsteen Cyprien <…>`__ | `Invoices to emit <…>`__ 670,00 SLS 32/2016 No
09/05/2016 `SLS 21/2016 <…>`__ `(4800) Internal clearings <…>`__ | `Adriensence Anastase <…>`__ | `Invoices to emit <…>`__ 990,00 SLS 21/2016 No
07/03/2016 `SLS 10/2016 <…>`__ `(4800) Internal clearings <…>`__ | `Reinhards Baumschule <…>`__ | `Invoices to emit <…>`__ 320,00 SLS 10/2016 No
**Balance -4090.00 (6 movements)** **4 090,00**
============ ===================== ============================================================================================= ======= ============== ============= =========