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

roger : A customized Lino Voga site

A Lino Voga site with a few local customizations.

Used in Lino Voga specs.

The lino_book.projects.roger demo project illustrates some local customizations.

This page is a tested document and the following instructions are used for initialization:

>>> from lino import startup
>>> startup('lino_book.projects.roger.settings.doctests')
>>> from lino.api.doctest import *

A customized management of membership fees

The lino_voga.lib.roger.courses plugin demonstrates the following rules for handling memberships:

  • Membership costs 15€ per year.

  • Members get a discount on enrolments to courses.

  • Customers can freely decide whether they want to be members or not.

  • They become member by paying the membership fee.

To handle these rules, we have an additional field member_until on each pupil.

There is a custom data checker lino_voga.lib.roger.courses.MemberChecker

>>> dd.demo_date()
datetime.date(2015, 5, 22)
>>> rt.show(courses.Pupils)
... 
======================================== ================================= ================== ============ ===== ===== ======== ==============
 Name                                     Address                           Participant type   Section      LFV   CKK   Raviva   Mitglied bis
---------------------------------------- --------------------------------- ------------------ ------------ ----- ----- -------- --------------
 Hans Altenberg (MEL)                     Aachener Straße, 4700 Eupen       Member                          Yes   No    No       31/12/2015
 Annette Arens (MEC)                      Alter Malmedyer Weg, 4700 Eupen   Helper                          No    Yes   No       31/12/2015
 Laurent Bastiaensen (ME)                 Am Berg, 4700 Eupen               Non-member                      No    No    No       31/12/2015
 Bernd Brecht (ME)                        Aachen, Germany                   Member                          No    No    No       31/12/2015
 Ulrike Charlier (ME)                     Auenweg, 4700 Eupen               Helper                          No    No    No       31/12/2015
 Dorothée Demeulenaere (ME)               Auf'm Rain, 4700 Eupen            Non-member                      No    No    No       31/12/2016
 ...
 Hedi Radermacher (ME)                    4730 Raeren                       Non-member                      No    No    No       31/12/2015
 Jean Radermacher (ME)                    4730 Raeren                       Member                          No    No    No       31/12/2015
 Marie-Louise Vandenmeulenbos (MEC)       Amsterdam, Netherlands            Helper                          No    Yes   No       31/12/2015
 Didier di Rupo (MS)                      4730 Raeren                       Non-member         Herresbach   No    No    No
 Erna Ärgerlich (ME)                      4730 Raeren                       Member                          No    No    No       31/12/2015
 Otto Östges (MCS)                        4730 Raeren                       Helper             Eynatten     No    Yes   No
======================================== ================================= ================== ============ ===== ===== ======== ==============
>>> print(dd.plugins.ledger.suppress_movements_until)
None
>>> rt.show(checkdata.MessagesByChecker, 'courses.MemberChecker')
============= ====================================== ==========================================
 Responsible   Database object                        Message text
------------- -------------------------------------- ------------------------------------------
 Robin Rood    *Karl Kaivers (ME)*                    Member until 2015-12-31, but no payment.
 Robin Rood    *Laura Laschet (ME)*                   Member until 2015-12-31, but no payment.
 Robin Rood    *Josefine Leffin (MEL)*                Member until 2015-12-31, but no payment.
 Robin Rood    *Marie-Louise Meier (ME)*              Member until 2015-12-31, but no payment.
 Robin Rood    *Alfons Radermacher (ME)*              Member until 2015-12-31, but no payment.
 Robin Rood    *Christian Radermacher (MEL)*          Member until 2015-12-31, but no payment.
 Robin Rood    *Edgard Radermacher (ME)*              Member until 2015-12-31, but no payment.
 Robin Rood    *Guido Radermacher (ME)*               Member until 2015-12-31, but no payment.
 Robin Rood    *Hedi Radermacher (ME)*                Member until 2015-12-31, but no payment.
 Robin Rood    *Jean Radermacher (ME)*                Member until 2015-12-31, but no payment.
 Robin Rood    *Erna Ärgerlich (ME)*                  Member until 2015-12-31, but no payment.
 Robin Rood    *Jean Dupont (ME)*                     Member until 2015-12-31, but no payment.
 Robin Rood    *Marie-Louise Vandenmeulenbos (MEC)*   Member until 2015-12-31, but no payment.
 Robin Rood    *Bernd Brecht (ME)*                    Member until 2015-12-31, but no payment.
 Robin Rood    *Jérôme Jeanémart (ME)*                Member until 2015-12-31, but no payment.
============= ====================================== ==========================================
>>> acc = rt.models.ledger.CommonAccounts.membership_fees.get_object()
>>> print(acc)
(7310) Membership fees
>>> rt.show(ledger.MovementsByAccount, acc)
============ ============== ===================================== ======= ============ =============
 Value date   Voucher        Description                           Debit   Credit       Match
------------ -------------- ------------------------------------- ------- ------------ -------------
 22/12/2015   *CSH 5/2015*   *Faymonville Luc*                             15,00        **CSH 5:1**
 22/12/2015   *CSH 5/2015*   *Groteclaes Gregory*                          15,00        **CSH 5:2**
 22/12/2015   *CSH 5/2015*   *Hilgers Hildegard*                           15,00        **CSH 5:3**
 22/12/2015   *CSH 5/2015*   *Jacobs Jacqueline*                           15,00        **CSH 5:4**
 22/12/2015   *CSH 5/2015*   *Jonas Josef*                                 15,00        **CSH 5:5**
 22/11/2015   *CSH 4/2015*   *Dobbelstein-Demeulenaere Dorothée*           15,00        **CSH 4:1**
 22/11/2015   *CSH 4/2015*   *Emonts Daniel*                               15,00        **CSH 4:3**
 22/11/2015   *CSH 4/2015*   *Engels Edgar*                                15,00        **CSH 4:4**
 22/11/2015   *CSH 4/2015*   *Evers Eberhart*                              15,00        **CSH 4:2**
 22/10/2015   *CSH 3/2015*   *Demeulenaere Dorothée*                       15,00        **CSH 3:2**
 22/10/2015   *CSH 3/2015*   *Dericum Daniel*                              15,00        **CSH 3:1**
 22/02/2015   *CSH 2/2015*   *Charlier Ulrike*                             15,00        **CSH 2:1**
 22/01/2015   *CSH 1/2015*   *Altenberg Hans*                              15,00        **CSH 1:2**
 22/01/2015   *CSH 1/2015*   *Arens Annette*                               15,00        **CSH 1:1**
 22/01/2015   *CSH 1/2015*   *Bastiaensen Laurent*                         15,00        **CSH 1:3**
                             **Balance -225.00 (15 movements)**            **225,00**
============ ============== ===================================== ======= ============ =============

Django and the VatVoucher model mixin

This section is no longer needed since 20230829. It helped us to discover that when you call contenttypes.ContentType.objects.get_for_model() with an abstract Model class, Django creates a contenttype database record. We then optimized lino_react.react.Renderer.actor2json() to not fall into that pit anymore.

The code snippets in this section are not actively tested, but you may remove the #doctest: +SKIP and play.

The contenttypes framework seems to sometimes create an entry for the VatVoucher model mixin although this is an abstract model.

>>> from django.apps import apps
>>> cts = set([ct.model_class() for ct in contenttypes.ContentType.objects.all()])
>>> for m in apps.get_models():
...     if m in cts:
...         cts.remove(m)
>>> cts  
{None}
>>> for ct in contenttypes.ContentType.objects.all():  
...   if ct.model_class() is None:
...     print(ct)
vatvoucher

This is caused by the following method:

>>> get_for_model = contenttypes.ContentType.objects.get_for_model

When passing a non-existed Model class (that is abstract) it creates a contenttype database record. For example see how the contenttype count increasing when looking up abstract models:

>>> contenttypes.ContentType.objects.count()  
92
>>> users.UserAuthored._meta.abstract, contenttypes.ContentType.objects.filter(model="userauthored").count()  
(True, 0)

Now see when we look it up using get_for_model method:

>>> get_for_model(users.UserAuthored)  
<ContentType: userauthored>
>>> contenttypes.ContentType.objects.count()  
93

And there's one more contenttype object.

Database structure

>>> from lino.utils.diag import analyzer
>>> print(analyzer.show_db_overview())
... 
48 apps: lino, about, printing, system, jinja, react, help, users, office, xl, countries, contacts, phones, lists, beid, contenttypes, gfks, linod, checkdata, cal, courses, products, rooms, memo, excerpts, weasyprint, uploads, ledger, bevats, vat, trading, summaries, storage, invoicing, finan, sepa, notes, outbox, voga, export_excel, calview, wkhtmltopdf, appypod, changes, bootstrap3, publisher, staticfiles, sessions.
94 models:
=========================== ============================== ========= =======
 Name                        Default table                  #fields   #rows
--------------------------- ------------------------------ --------- -------
 bevats.Declaration          bevats.Declarations            28        15
 cal.Calendar                cal.Calendars                  6         8
 cal.EntryRepeater           cal.EntryRepeaterTable         17        0
 cal.Event                   cal.Events                     25        1171
 cal.EventPolicy             cal.EventPolicies              20        6
 cal.EventType               cal.EventTypes                 24        10
 cal.Guest                   cal.Guests                     6         0
 cal.GuestRole               cal.GuestRoles                 5         3
 cal.RecurrentEvent          cal.RecurrentEvents            22        16
 cal.RemoteCalendar          cal.RemoteCalendars            7         0
 cal.Room                    cal.Rooms                      11        7
 cal.Subscription            cal.Subscriptions              4         35
 cal.Task                    cal.Tasks                      16        0
 calview.DailyPlannerRow     calview.DailyPlannerRows       7         2
 changes.Change              changes.Changes                10        0
 checkdata.Message           checkdata.Messages             6         ...
 contacts.Company            contacts.Companies             26        31
 contacts.CompanyType        contacts.CompanyTypes          7         16
 contacts.Partner            contacts.Partners              24        103
 contacts.Person             contacts.Persons               42        72
 contacts.Role               contacts.Roles                 4         3
 contacts.RoleType           contacts.RoleTypes             5         5
 contenttypes.ContentType    gfks.ContentTypes              3         94
 countries.Country           countries.Countries            6         10
 countries.Place             countries.Places               9         80
 courses.Course              courses.Activities             34        26
 courses.CourseType          courses.CourseTypes            5         0
 courses.Enrolment           courses.Enrolments             17        95
 courses.Line                courses.Lines                  25        10
 courses.Pupil               courses.Pupils                 51        35
 courses.PupilType           courses.PupilTypes             5         3
 courses.Slot                courses.Slots                  5         0
 courses.Teacher             courses.Teachers               44        9
 courses.TeacherType         courses.TeacherTypes           5         4
 courses.Topic               courses.Topics                 4         5
 excerpts.Excerpt            excerpts.Excerpts              11        ...
 excerpts.ExcerptType        excerpts.ExcerptTypes          17        15
 finan.BankStatement         finan.BankStatements           16        21
 finan.BankStatementItem     finan.BankStatementItemTable   9         368
 finan.JournalEntry          finan.FinancialVouchers        14        0
 finan.JournalEntryItem      finan.JournalEntryItemTable    9         0
 finan.PaymentOrder          finan.PaymentOrders            15        16
 finan.PaymentOrderItem      finan.PaymentOrderItemTable    9         127
 invoicing.FollowUpRule      invoicing.FollowUpRules        5         4
 invoicing.Item              invoicing.Items                10        16
 invoicing.Plan              invoicing.Plans                8         1
 invoicing.SalesRule         invoicing.SalesRules           3         4
 invoicing.Tariff            invoicing.Tariffs              8         0
 invoicing.Task              invoicing.Tasks                28        1
 ledger.Account              ledger.Accounts                18        21
 ledger.AccountingPeriod     ledger.AccountingPeriods       7         17
 ledger.FiscalYear           ledger.FiscalYears             5         7
 ledger.Journal              ledger.Journals                27        10
 ledger.LedgerInfo           ledger.LedgerInfoTable         2         0
 ledger.MatchRule            ledger.MatchRules              3         33
 ledger.Movement             ledger.Movements               11        1453
 ledger.PaymentTerm          ledger.PaymentTerms            11        8
 ledger.Voucher              ledger.AllVouchers             8         423
 linod.SystemTask            linod.SystemTasks              24        4
 lists.List                  lists.Lists                    7         8
 lists.ListType              lists.ListTypes                4         3
 lists.Member                lists.Members                  5         103
 memo.Mention                memo.Mentions                  5         0
 notes.EventType             notes.EventTypes               8         1
 notes.Note                  notes.Notes                    16        100
 notes.NoteType              notes.NoteTypes                11        3
 outbox.Attachment           outbox.Attachments             4         0
 outbox.Mail                 outbox.Mails                   8         63
 outbox.Recipient            outbox.Recipients              6         63
 phones.ContactDetail        phones.ContactDetails          8         79
 products.Category           products.Categories            15        5
 products.PriceRule          products.PriceRules            4         0
 products.Product            products.Products              21        12
 rooms.Booking               rooms.Bookings                 24        3
 sepa.Account                sepa.Accounts                  6         25
 sessions.Session            users.Sessions                 3         ...
 storage.Component           storage.Components             4         3
 storage.DeliveryItem        storage.DeliveryItems          8         0
 storage.DeliveryNote        storage.DeliveryNotes          14        0
 storage.Filler              storage.Fillers                6         19
 storage.Movement            storage.Movements              10        264
 storage.Provision           storage.Provisions             5         0
 storage.TransferRule        storage.TransferRules          5         0
 system.SiteConfig           system.SiteConfigs             12        1
 trading.InvoiceItem         trading.InvoiceItems           15        582
 trading.PaperType           trading.PaperTypes             5         2
 trading.VatProductInvoice   trading.Invoices               27        252
 uploads.Upload              uploads.Uploads                12        7
 uploads.UploadType          uploads.UploadTypes            8         1
 uploads.Volume              uploads.Volumes                5         0
 users.Authority             users.Authorities              3         0
 users.User                  users.AllUsers                 19        6
 vat.InvoiceItem             vat.InvoiceItemTable           9         187
 vat.VatAccountInvoice       vat.Invoices                   20        119
=========================== ============================== ========= =======

Foreign Keys and their on_delete setting

Here is a list of foreign keys in Lino Voga and their on_delete behaviour. See also Customize delete behaviour.

>>> from lino.utils.diag import analyzer
>>> print(analyzer.show_foreign_keys())
... 
- cal.Calendar :
  - CASCADE : cal.Subscription.calendar
  - PROTECT : cal.Room.calendar, system.SiteConfig.site_calendar
- cal.Event :
  - CASCADE : cal.Guest.event
  - PROTECT : cal.EntryRepeater.cal_entry
- cal.EventType :
  - PROTECT : cal.Event.event_type, cal.EventPolicy.event_type, cal.RecurrentEvent.event_type, courses.Line.event_type, products.PriceRule.selector, rooms.Booking.event_type, system.SiteConfig.default_event_type, users.User.event_type
- cal.GuestRole :
  - PROTECT : cal.Guest.role, courses.Line.guest_role, system.SiteConfig.pupil_guestrole
- cal.Room :
  - PROTECT : cal.Event.room, courses.Course.room, rooms.Booking.room
- contacts.Company :
  - PROTECT : cal.Room.company, contacts.Role.company, courses.Line.company, excerpts.Excerpt.company, ledger.Journal.partner, notes.Note.company, rooms.Booking.company, system.SiteConfig.site_company
- contacts.CompanyType :
  - PROTECT : contacts.Company.type
- contacts.Partner :
  - CASCADE : contacts.Company.partner_ptr, contacts.Person.partner_ptr, invoicing.Item.partner, invoicing.SalesRule.partner, lists.Member.partner, phones.ContactDetail.partner, sepa.Account.partner
  - PROTECT : bevats.Declaration.partner, finan.BankStatementItem.partner, finan.JournalEntryItem.partner, finan.PaymentOrderItem.partner, invoicing.Plan.partner, invoicing.SalesRule.invoice_recipient, ledger.Movement.partner, outbox.Recipient.partner, storage.DeliveryNote.partner, storage.Filler.partner, storage.Movement.partner, storage.Provision.partner, trading.VatProductInvoice.partner, users.User.partner, vat.VatAccountInvoice.partner
- contacts.Person :
  - CASCADE : courses.Pupil.person_ptr, courses.Teacher.person_ptr
  - PROTECT : cal.Guest.partner, cal.Room.contact_person, contacts.Role.person, courses.Line.contact_person, excerpts.Excerpt.contact_person, notes.Note.contact_person, rooms.Booking.contact_person
- contacts.RoleType :
  - PROTECT : cal.Room.contact_role, contacts.Role.type, courses.Line.contact_role, excerpts.Excerpt.contact_role, notes.Note.contact_role, rooms.Booking.contact_role
- contenttypes.ContentType :
  - PROTECT : cal.Event.owner_type, cal.Task.owner_type, changes.Change.master_type, changes.Change.object_type, checkdata.Message.owner_type, excerpts.Excerpt.owner_type, excerpts.ExcerptType.content_type, invoicing.FollowUpRule.invoice_generator, invoicing.Item.generator_type, memo.Mention.owner_type, memo.Mention.source_type, notes.Note.owner_type, outbox.Attachment.owner_type, outbox.Mail.owner_type, storage.DeliveryItem.invoiceable_type, trading.InvoiceItem.invoiceable_type, uploads.Upload.owner_type
- countries.Country :
  - PROTECT : contacts.Partner.country, contacts.Person.birth_country, contacts.Person.nationality, countries.Place.country
- countries.Place :
  - PROTECT : contacts.Partner.city, contacts.Partner.region, countries.Place.parent
- courses.Course :
  - PROTECT : courses.Enrolment.course, invoicing.Plan.order
- courses.CourseType :
  - PROTECT : courses.Line.course_type
- courses.Line :
  - PROTECT : courses.Course.line
- courses.Pupil :
  - PROTECT : courses.Enrolment.pupil
- courses.PupilType :
  - PROTECT : courses.Pupil.pupil_type
- courses.Slot :
  - PROTECT : courses.Course.slot
- courses.Teacher :
  - PROTECT : courses.Course.teacher
- courses.TeacherType :
  - PROTECT : courses.Teacher.teacher_type
- courses.Topic :
  - PROTECT : courses.Line.topic
- excerpts.Excerpt :
  - SET_NULL : bevats.Declaration.printed_by, courses.Enrolment.printed_by, finan.BankStatement.printed_by, finan.JournalEntry.printed_by, finan.PaymentOrder.printed_by, storage.DeliveryNote.printed_by, trading.VatProductInvoice.printed_by
- excerpts.ExcerptType :
  - PROTECT : excerpts.Excerpt.excerpt_type
- finan.BankStatement :
  - CASCADE : finan.BankStatementItem.voucher
- finan.JournalEntry :
  - CASCADE : finan.JournalEntryItem.voucher
- finan.PaymentOrder :
  - CASCADE : finan.PaymentOrderItem.voucher
- invoicing.Plan :
  - CASCADE : invoicing.Item.plan
- invoicing.Task :
  - CASCADE : invoicing.FollowUpRule.invoicing_task
  - PROTECT : invoicing.Plan.invoicing_task
- ledger.Account :
  - PROTECT : finan.BankStatement.item_account, finan.BankStatementItem.account, finan.JournalEntry.item_account, finan.JournalEntryItem.account, finan.PaymentOrder.item_account, finan.PaymentOrderItem.account, ledger.Journal.account, ledger.MatchRule.account, ledger.Movement.account, vat.InvoiceItem.account
- ledger.AccountingPeriod :
  - PROTECT : bevats.Declaration.end_period, bevats.Declaration.start_period, ledger.Voucher.accounting_period
- ledger.FiscalYear :
  - PROTECT : ledger.AccountingPeriod.year
- ledger.Journal :
  - CASCADE : invoicing.FollowUpRule.source_journal, ledger.MatchRule.journal
  - PROTECT : invoicing.Task.target_journal, ledger.Voucher.journal, storage.TransferRule.journal
- ledger.PaymentTerm :
  - PROTECT : bevats.Declaration.payment_term, contacts.Partner.payment_term, courses.Course.payment_term, trading.VatProductInvoice.payment_term, vat.VatAccountInvoice.payment_term
- ledger.Voucher :
  - CASCADE : ledger.Movement.voucher, storage.Movement.voucher
  - PROTECT : bevats.Declaration.voucher_ptr, finan.BankStatement.voucher_ptr, finan.JournalEntry.voucher_ptr, finan.PaymentOrder.voucher_ptr, storage.DeliveryNote.voucher_ptr, trading.VatProductInvoice.voucher_ptr, vat.VatAccountInvoice.voucher_ptr
  - SET_NULL : invoicing.Item.invoice
- lists.List :
  - CASCADE : lists.Member.list
- lists.ListType :
  - PROTECT : lists.List.list_type
- notes.EventType :
  - PROTECT : notes.Note.event_type, system.SiteConfig.system_note_type
- notes.NoteType :
  - PROTECT : notes.Note.type
- outbox.Mail :
  - CASCADE : outbox.Attachment.mail, outbox.Recipient.mail
- products.Category :
  - PROTECT : courses.Line.fees_cat, courses.Line.options_cat, products.Category.parent, products.Product.category
- products.Product :
  - PROTECT : cal.Room.fee, courses.Course.fee, courses.Enrolment.fee, courses.Enrolment.option, courses.Line.fee, invoicing.Tariff.product, products.PriceRule.product, storage.Component.child, storage.Component.parent, storage.DeliveryItem.product, storage.Filler.provision_product, storage.Movement.product, storage.Provision.product, trading.InvoiceItem.product
- sepa.Account :
  - PROTECT : finan.PaymentOrderItem.bank_account, ledger.Journal.sepa_account
- storage.DeliveryNote :
  - CASCADE : storage.DeliveryItem.voucher
- trading.PaperType :
  - PROTECT : courses.Course.paper_type, invoicing.SalesRule.paper_type, trading.VatProductInvoice.paper_type
- trading.VatProductInvoice :
  - CASCADE : trading.InvoiceItem.voucher
- uploads.UploadType :
  - PROTECT : uploads.Upload.type
- uploads.Volume :
  - PROTECT : ledger.Journal.uploads_volume, uploads.Upload.volume
- users.User :
  - CASCADE : cal.Subscription.user, ledger.LedgerInfo.user
  - PROTECT : cal.Event.assigned_to, cal.Event.user, cal.RecurrentEvent.user, cal.Task.user, changes.Change.user, checkdata.Message.user, courses.Course.user, courses.Enrolment.user, excerpts.Excerpt.user, invoicing.Plan.user, invoicing.Task.user, ledger.Voucher.user, notes.Note.user, outbox.Mail.user, rooms.Booking.user, uploads.Upload.user, users.Authority.authorized, users.Authority.user
- vat.VatAccountInvoice :
  - CASCADE : vat.InvoiceItem.voucher

Don't read me

The snippets in this section are just for testing.

>>> pprint(settings.SITE.installed_plugins)
(lino,
 lino.modlib.about,
 lino.modlib.printing (needed_by=lino.modlib.system),
 lino.modlib.system (needed_by=lino_react.react, needs_plugins=['lino.modlib.printing']),
 lino.modlib.jinja (needed_by=lino_react.react),
 lino_react.react (media_name=react, needs_plugins=['lino.modlib.system', 'lino.modlib.jinja']),
 lino.modlib.help (needs_plugins=['lino.modlib.system']),
 lino.modlib.users (needs_plugins=['lino.modlib.system']),
 lino.modlib.office (needed_by=lino_xl.lib.countries),
 lino_xl.lib.xl (needed_by=lino_xl.lib.countries),
 lino_xl.lib.countries (needs_plugins=['lino.modlib.office', 'lino_xl.lib.xl']),
 lino_voga.lib.contacts (extends_models=['Person'], needs_plugins=['lino_xl.lib.countries', 'lino.modlib.system']),
 lino_xl.lib.phones,
 lino_xl.lib.lists,
 lino_xl.lib.beid (media_name=eidreader),
 django.contrib.contenttypes (needed_by=lino.modlib.gfks),
 lino.modlib.gfks (needed_by=lino.modlib.checkdata, needs_plugins=['lino.modlib.system', 'django.contrib.contenttypes']),
 lino.modlib.linod (needed_by=lino.modlib.checkdata),
 lino.modlib.checkdata (needs_plugins=['lino.modlib.users', 'lino.modlib.gfks', 'lino.modlib.linod']),
 lino_voga.lib.cal (extends_models=['Event', 'Room'], needs_plugins=['lino.modlib.gfks', 'lino.modlib.printing', 'lino_xl.lib.xl', 'lino.modlib.checkdata', 'lino.modlib.linod']),
 lino_voga.lib.roger.courses (extends_models=['Pupil', 'Enrolment', 'Line'], needs_plugins=['lino_xl.lib.cal']),
 lino_voga.lib.products (extends_models=['Product', 'Category'], needs_plugins=['lino_xl.lib.xl']),
 lino_voga.lib.rooms (extends_models=['Booking']),
 lino.modlib.memo (needed_by=lino_voga.lib.trading, needs_plugins=['lino.modlib.office', 'lino.modlib.gfks']),
 lino_xl.lib.excerpts (needed_by=lino_xl.lib.vat, needs_plugins=['lino.modlib.gfks', 'lino.modlib.printing', 'lino.modlib.office', 'lino_xl.lib.xl']),
 lino.modlib.weasyprint (needed_by=lino_xl.lib.ledger),
 lino.modlib.uploads (needed_by=lino_xl.lib.ledger),
 lino_xl.lib.ledger (needed_by=lino_xl.lib.vat, needs_plugins=['lino.modlib.weasyprint', 'lino_xl.lib.xl', 'lino.modlib.uploads']),
 lino_xl.lib.bevats (needed_by=lino_xl.lib.vat, needs_plugins=['lino_xl.lib.vat']),
 lino_xl.lib.vat (needed_by=lino_voga.lib.trading, needs_plugins=['lino.modlib.checkdata', 'lino_xl.lib.excerpts']),
 lino_voga.lib.trading (needs_plugins=['lino.modlib.memo', 'lino_xl.lib.products', 'lino_xl.lib.vat']),
 lino.modlib.summaries (needed_by=lino_xl.lib.storage),
 lino_xl.lib.storage (needs_plugins=['lino_xl.lib.products', 'lino.modlib.summaries']),
 lino_xl.lib.invoicing (needs_plugins=['lino_xl.lib.trading']),
 lino_xl.lib.finan (needs_plugins=['lino_xl.lib.ledger']),
 lino_xl.lib.sepa (needs_plugins=['lino_xl.lib.ledger']),
 lino_xl.lib.notes (needs_plugins=['lino.modlib.memo']),
 lino_xl.lib.outbox (needs_plugins=['lino.modlib.uploads']),
 lino_voga.lib.voga,
 lino.modlib.export_excel,
 lino_xl.lib.calview (needs_plugins=['lino_xl.lib.cal']),
 lino.modlib.wkhtmltopdf,
 lino_xl.lib.appypod,
 lino.modlib.changes (needs_plugins=['lino.modlib.users', 'lino.modlib.gfks']),
 lino.modlib.bootstrap3 (media_name=bootstrap-3.3.4, needed_by=lino.modlib.publisher, needs_plugins=['lino.modlib.jinja']),
 lino.modlib.publisher (needs_plugins=['lino.modlib.jinja', 'lino.modlib.bootstrap3']),
 django.contrib.staticfiles,
 django.contrib.sessions)