Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More
invoicing
in Noi¶
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.noi1r.startup import *
Overview¶
A subscription generates one invoice per year or month. Each invoice for a
same customer has the same amount. Working sessions
generate service reports, which are just internal
delivery notes, not invoices. Fillers monitor the time credit of customers
and generate an invoice to buy new credit when needed. And the first invoice
generator, lino_xl.lib.trading.InvoiceItem
, is not used.
>>> rt.show(accounting.JournalsOverview)
**39 Sales invoices (SLS)**
**8 Subscription invoices (SUB)**
**55 Service reports (SRV)**
**5 Service Level Agreements (SLA)**
>>> rt.show('invoicing.Tasks')
...
===== ================================== ========== =========== =======================
No. Name Disabled When Status
----- ---------------------------------- ---------- ----------- -----------------------
1 Make Service reports (SRV) No Every day Scheduled to run asap
2 Make Sales invoices (SLS) No Every day Scheduled to run asap
3 Make Subscription invoices (SUB) No Every day Scheduled to run asap
===== ================================== ========== =========== =======================
These are the invoice generators in Noi:
>>> pprint(rt.models_by_base(invoicing.InvoiceGenerator))
[<class 'lino_xl.lib.storage.models.Filler'>,
<class 'lino_xl.lib.subscriptions.models.SubscriptionPeriod'>,
<class 'lino_xl.lib.trading.models.InvoiceItem'>,
<class 'lino_xl.lib.working.models.Session'>]
Note that the reporting
area should run one day before the default
area.
Subscription invoices get created based on the subscription periods (which in turn get created as summary data of the actual subscriptions one per year or month).
Sales invoices get created based on service reports and storage fillers.
Service reports get created based on working sessions.
>>> rt.show('invoicing.FollowUpRules')
===== ====================================================== ====================== ================
No. Invoicing task Invoice generator Source journal
----- ------------------------------------------------------ ---------------------- ----------------
1 Invoicing task #1 (Make Service reports (SRV)) Working session
2 Invoicing task #3 (Make Subscription invoices (SUB)) Subscription period
3 Invoicing task #2 (Make Sales invoices (SLS)) Storage filler
4 Invoicing task #2 (Make Sales invoices (SLS)) Trading invoice item
===== ====================================================== ====================== ================
#5386 (detail link on a ledger movement causes traceback)¶
>>> obj = rt.models.trading.VatProductInvoice.objects.filter(partner=1).last()
>>> obj
VatProductInvoice #104 ('SLS 8/2015')
>>> obj.partner
Partner #1 ('Rumma & Ko OÜ')
>>> rt.show('trading.ItemsByInvoice', obj)
==================== ============================================ ========= =========== ==== ============ ====================================================
Product Designation UPr Qty D% Amount InvObj
-------------------- -------------------------------------------- --------- ----------- ---- ------------ ----------------------------------------------------
Filler Rumma & Ko OÜ Purchased Hourly rate `Filler Rumma & Ko OÜ Purchased Hourly rate <…>`__
Hourly rate Hourly rate 60,0000 15:34 934,00
**Total (2 rows)** **15:34** **934,00**
==================== ============================================ ========= =========== ==== ============ ====================================================
>>> ar = rt.login("robin")
>>> rnd = settings.SITE.kernel.default_renderer
The default table for a trading.VatProductInvoice
is
trading.Invoices
:
>>> obj.__class__.get_default_table()
lino_xl.lib.trading.ui.Invoices
The detail_link of an invoice points to trading.InvoicesByJournal
because the detail_layout to use depends on the journal’s voucher type.
>>> obj.get_detail_action(ar)
<BoundAction(trading.InvoicesByJournal, <lino.core.actions.ShowDetail detail ('Detail')>)>
The following link is actually broken because it doesn’t specify the master instance (the journal) to InvoicesByJournal:
>>> print(rnd.obj2url(ar, obj))
javascript:window.App.runAction({ "actorId": "trading.InvoicesByJournal", "an": "detail", "rp": null, "status": { "record_id": 104 } })
>>> print(rnd.obj2htmls(ar, obj))
...
<a href="javascript:window.App.runAction({ "actorId":
"trading.InvoicesByJournal", "an": "detail",
"rp": null, "status": { "record_id": 104 } })"
style="text-decoration:none">SLS 8/2015</a>
>>> for wm in obj.get_wanted_movements():
... print(wm.__class__, wm.product)
<class 'lino_xl.lib.storage.models.Movement'> Hourly rate
<class 'lino_xl.lib.accounting.models.Movement'> None
<class 'lino_xl.lib.accounting.models.Movement'> None