Miscellaneous

Side note: Code snippets (lines starting with >>>) in this document get tested as part of our development workflow. The following initialization snippet tells you which demo project is being used in this document.

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

Build all excerpts

Default template for excerpts

Check whether Lino returns the right default template for excerpts.

In lino_xl.lib.excerpts we define a template excerpts/Default.odt, but lino_welfare.modlib.welfare overrides this template.

The rule is that the *last* plugin wins when Lino searches for templates.

This means that if we want to see the welfare-specific version, our get_installed_plugins in lino_welare.projects.std.settings must yield lino_welfare.modlib.welfare after lino_xl.lib.excerpts.

The following test verifies this rule:

>>> print(settings.SITE.find_config_file('Default.odt', 'excerpts'))
... 
/.../welfare/config/excerpts/Default.odt

Editing the print template of an excerpt

Here we want to see what the EditTemplate action says, especially when called on an excerpt where Lino has two possible locations.

Note that we need a local config directory for the following test to work. On travis we use LINO_CACHE_ROOT, so there is no local config dir. That’s why this doctest must create one.

>>> lcd = settings.SITE.site_dir / 'config'
>>> rt.makedirs_if_missing(lcd)

After having created the directory, we must tell Lino to scan the file system again:

>>> settings.SITE.confdirs.scan_config_dirs()
>>> settings.SITE.confdirs.LOCAL_CONFIG_DIR.writeable
True

Excerpts are printables with two template groups. A printable with several template groups will use the first one that exists, and will fail only if non of them exists. The first template group is given by the owner (e.g. “immersion/Contract”) and the second is just “excerpts”. For example the owner of Excerpt #2 is an immersion training, while the owner of Excerpt #4 is an aids confirmation:

>>> excerpts.Excerpt.objects.get(pk=2).get_template_groups() 
['immersion/Contract', 'excerpts']
>>> excerpts.Excerpt.objects.get(pk=4).get_template_groups() 
['aids/Confirmation', 'excerpts']

When creating a local copy of the factory template, Lino copies the factory file to the directory given by the first group. Before doing so, it will ask for user confirmation. The following code snippet partly tests this situation.

>>> obj = excerpts.Excerpt.objects.get(pk=2)
>>> obj.owner
Contract #2 ("Stage d'immersion#2 (Edgar ENGELS)")
>>> ses.set_confirm_answer(False)
>>> with ses.capture_logger('DEBUG') as out:
...    rv = ses.run(obj.edit_template)
>>> print(out.getvalue())  
Gonna copy ...welfare/config/excerpts/Default.odt to .../config/immersion/Contract/Default.odt
>>> print(rv['message'])  
Before you can edit this template we must create a local copy on the server. This will exclude the template from future updates.
D'accord?

Another thing is the location of the factory template.

>>> obj = excerpts.Excerpt.objects.get(pk=1)
>>> ses.set_confirm_answer(False)
>>> with ses.capture_logger('DEBUG') as out:
...     rv = ses.run(obj.edit_template)
>>> print(out.getvalue())  
Gonna copy .../lino_welfare/modlib/welfare/config/excerpts/Default.odt to .../config/immersion/Contract/Default.odt

Yet another series of GET requests

>>> ContentType = rt.models.contenttypes.ContentType
>>> json_fields = 'count rows title success no_data_text param_values'
>>> kw = dict(fmt='json', limit=10, start=0)
>>> demo_get('rolf', 'api/contacts/Companies', json_fields, 37, **kw)
>>> demo_get('rolf', 'api/households/Households', json_fields, 15, **kw)
>>> demo_get('rolf', 'api/contacts/Partners', json_fields, 147, **kw)
>>> demo_get('rolf', 'api/jobs/JobProviders', json_fields, 4, **kw)
>>> json_fields = 'count rows title success no_data_text'
>>> demo_get('rolf', 'api/countries/Countries', json_fields, 225, **kw)
>>> demo_get('rolf', 'api/jobs/Jobs', json_fields, 9, **kw)
>>> json_fields = 'count rows title success no_data_text param_values'
>>> demo_get('rolf', 'api/contacts/Persons', json_fields, 97, **kw)
>>> demo_get('rolf', 'api/pcsw/CoachedClients', json_fields, 29, **kw)
>>> demo_get('rolf', 'api/debts/Clients', json_fields, 0, **kw)
>>> demo_get('rolf', 'api/cal/MyEntries', json_fields, 9, **kw)
>>> demo_get('rolf', 'api/newcomers/NewClients', json_fields, 22, **kw)

Value for mt in the following snippets:

>>> mt = contenttypes.ContentType.objects.get_for_model(pcsw.Client).pk
>>> demo_get(
...    'rolf', 'api/newcomers/AvailableCoachesByClient', json_fields,
...    2, mt=mt, mk=120, **kw)
>>> demo_get('alicia', 'api/integ/Clients', json_fields, 7, **kw)
>>> demo_get('hubert', 'api/integ/Clients', json_fields, 17, **kw)
>>> alicia = settings.SITE.user_model.objects.get(username='alicia')

Rolf working as Alicia:

>>> kw = dict(fmt='json', limit=20, start=0, su=alicia.pk)
>>> demo_get('rolf', 'api/integ/Clients', json_fields, 7, **kw)

Some choices lists:

>>> kw = dict()
>>> fields = 'count rows'
>>> demo_get(
...    'rolf', 'choices/aids/IncomeConfirmations/aid_type', fields, 11, **kw)
>>> demo_get(
...    'rolf', 'choices/aids/RefundConfirmations/aid_type', fields, 11, **kw)
>>> demo_get(
...    'rolf', 'apchoices/pcsw/Clients/create_visit/user', fields, 4, **kw)
>>> demo_get(
...    'robin', 'choices/countries/Countries/actual_country', fields, 220, **kw)
>>> kw.update(mt=mt, mk=120, type=1)  # slave table requires a master instance
>>> demo_get(
...    'rolf', 'choices/clients/ContactsByClient/company', fields, 3, **kw)

Visibility of eID reader action

Here is a list of the tables that have the lino.modlib.beid.mixins.FindByBeIdAction and the user profiles that can see it.

>>> from lino_xl.lib.beid.mixins import FindByBeIdAction
>>> print(analyzer.show_action_permissions(FindByBeIdAction))
... 
- debts.Clients.find_by_beid : visible for 120 300 420 admin 910
- integ.Clients.find_by_beid : visible for 100 110 120 130 420 admin 910
- newcomers.ClientsByFaculty.find_by_beid : visible for 100 110 120 130 200 210 220 300 400 410 420 430 800 admin 910
- newcomers.NewClients.find_by_beid : visible for 120 200 220 300 420 admin 910
- pcsw.AllClients.find_by_beid : visible for 110 120 410 420 admin 910
- pcsw.Clients.find_by_beid : visible for 100 110 120 130 200 210 220 300 400 410 420 430 800 admin 910
- pcsw.ClientsByNationality.find_by_beid : visible for 100 110 120 130 200 210 220 300 400 410 420 430 800 admin 910
- pcsw.CoachedClients.find_by_beid : visible for 100 110 120 130 200 300 400 410 420 430 admin 910
- reception.Clients.find_by_beid : visible for 100 110 120 130 200 210 220 300 400 410 420 430 800 admin 910

Visibility of duplicate action

Here is a list of the tables that have the lino.mixins.duplicable.Duplicate and the user types that can see it.

>>> from lino.mixins.duplicable import Duplicate
>>> print(analyzer.show_action_permissions(Duplicate))
... 
- cal.AllEntries.duplicate : visible for admin 910
- cal.ConflictingEvents.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 500 510 admin 910
- cal.EntriesByClient.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- cal.EntriesByController.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- cal.EntriesByDay.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- cal.EntriesByGuest.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- cal.EntriesByProject.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- cal.EntriesByRoom.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 500 510 admin 910
- cal.EntriesByType.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 500 510 admin 910
- cal.EventTypes.duplicate : visible for 110 120 410 420 admin 910
- cal.Events.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 500 510 admin 910
- cal.MyAssignedEvents.duplicate : visible for 100 110 120 130 200 300 400 410 420 430 500 510 admin 910
- cal.MyEntries.duplicate : visible for 100 110 120 130 200 300 400 410 420 430 500 510 admin 910
- cal.MyEntriesToday.duplicate : visible for 100 110 120 130 200 300 400 410 420 430 500 510 admin 910
- cal.MyOverdueAppointments.duplicate : visible for 100 110 120 130 200 300 400 410 420 430 500 510 admin 910
- cal.MyUnconfirmedAppointments.duplicate : visible for 100 110 120 130 200 300 400 410 420 430 500 510 admin 910
- cal.OneEvent.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- cal.OverdueAppointments.duplicate : visible for 110 120 410 420 admin 910
- cal.PublicEntries.duplicate : visible for 130 210 430
- cal.RemoteCalendars.duplicate : visible for 110 120 410 420 admin 910
- calview.DailyPlanner.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- calview.DailyPlannerRows.duplicate : visible for 110 120 410 420 admin 910
- calview.DailySlave.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- calview.WeeklySlave.duplicate : visible for 110 120 410 420 admin 910
- cbss.AllIdentifyPersonRequests.duplicate : visible for admin 910
- cbss.AllManageAccessRequests.duplicate : visible for admin 910
- cbss.AllRetrieveTIGroupsRequests.duplicate : visible for admin 910
- cbss.IdentifyPersonRequests.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 admin 910
- cbss.IdentifyRequestsByPerson.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 admin 910
- cbss.ManageAccessRequests.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 admin 910
- cbss.ManageAccessRequestsByPerson.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 admin 910
- cbss.MyIdentifyPersonRequests.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 admin 910
- cbss.MyManageAccessRequests.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 admin 910
- cbss.MyRetrieveTIGroupsRequests.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 admin 910
- cbss.RetrieveTIGroupsRequests.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 admin 910
- cbss.RetrieveTIGroupsRequestsByPerson.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 admin 910
- clients.PartnersByClientContactType.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- coachings.CoachingEndings.duplicate : visible for 110 120 130 210 410 420 430 admin 910
- contacts.Companies.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- contacts.Partners.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- contacts.PartnersByCity.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- contacts.PartnersByCountry.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- contacts.Persons.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- countries.Places.duplicate : visible for 110 120 130 210 410 420 430 800 admin 910
- countries.PlacesByCountry.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- countries.PlacesByPlace.duplicate : visible for 110 120 130 210 410 420 430 800 admin 910
- courses.ActiveActivities.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.Activities.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.ActivitiesByLayout.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.ActivitiesByLine.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.ActivitiesBySlot.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.ActivitiesByTeacher.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.ActivitiesByTopic.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.AllActivities.duplicate : visible for admin 910
- courses.ClosedActivities.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.DraftActivities.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.EntriesByTeacher.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 500 510 admin 910
- courses.InactiveActivities.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.JobCourses.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.Lines.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.LinesByTopic.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.MyActivities.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 800 admin 910
- courses.MyCoursesGiven.duplicate : visible for 110 120 420 admin 910
- courses.Slots.duplicate : visible for admin 910
- courses.Topics.duplicate : visible for admin 910
- cv.EducationLevels.duplicate : visible for 110 120 420 admin 910
- dashboard.AllWidgets.duplicate : visible for admin 910
- dashboard.Widgets.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- dashboard.WidgetsByUser.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- debts.Accounts.duplicate : visible for admin 910
- debts.AccountsByGroup.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- debts.Actors.duplicate : visible for admin 910
- debts.ActorsByBudget.duplicate : visible for 120 300 420 admin 910
- debts.ActorsByPartner.duplicate : visible for 120 300 420 admin 910
- debts.AssetsByBudget.duplicate : visible for 120 300 420 admin 910
- debts.Budgets.duplicate : visible for admin 910
- debts.BudgetsByPartner.duplicate : visible for 120 300 420 admin 910
- debts.Clients.duplicate : visible for 120 300 420 admin 910
- debts.DistByBudget.duplicate : visible for 120 300 420 admin 910
- debts.Entries.duplicate : visible for admin 910
- debts.EntriesByAccount.duplicate : visible for admin 910
- debts.EntriesByBudget.duplicate : visible for 120 300 420 admin 910
- debts.EntriesByType.duplicate : visible for 120 300 420 admin 910
- debts.ExpensesByBudget.duplicate : visible for 120 300 420 admin 910
- debts.IncomesByBudget.duplicate : visible for 120 300 420 admin 910
- debts.LiabilitiesByBudget.duplicate : visible for 120 300 420 admin 910
- debts.MyBudgets.duplicate : visible for 120 300 420 admin 910
- excerpts.AllExcerpts.duplicate : visible for admin 910
- excerpts.ExcerptTypes.duplicate : visible for admin 910
- excerpts.Excerpts.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- excerpts.ExcerptsByOwner.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- excerpts.ExcerptsByProject.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 500 510 800 admin 910
- excerpts.ExcerptsByType.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- excerpts.MyExcerpts.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- extensible.PanelEvents.duplicate : visible for 100 110 120 130 200 300 400 410 420 430 500 510 admin 910
- households.Households.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 500 510 800 admin 910
- households.HouseholdsByType.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 500 510 800 admin 910
- integ.Clients.duplicate : visible for 100 110 120 130 420 admin 910
- integ.CoachingEndingsByType.duplicate : visible for 110 120 130 210 410 420 430 admin 910
- integ.CoachingEndingsByUser.duplicate : visible for 110 120 130 210 410 420 430 admin 910
- integ.CompaniesAndContracts.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- integ.JobProvidersAndContracts.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- isip.EntriesByContract.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- jobs.Employers.duplicate : visible for 100 110 120 130 420 admin 910
- jobs.JobProviders.duplicate : visible for 100 110 120 130 420 admin 910
- jobs.JobTypes.duplicate : visible for 110 120 410 420 admin 910
- jobs.WorkplacesByProvider.duplicate : visible for 100 110 120 130 420 admin 910
- linod.SystemTasks.duplicate : visible for admin 910
- newcomers.ClientsByFaculty.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- newcomers.Competences.duplicate : visible for 110 120 410 420 admin 910
- newcomers.CompetencesByFaculty.duplicate : visible for 110 120 410 420 admin 910
- newcomers.CompetencesByUser.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- newcomers.MyCompetences.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- newcomers.NewClients.duplicate : visible for 120 200 220 300 420 admin 910
- notes.AllNotes.duplicate : visible for 110 120 420 admin 910
- notes.MyNotes.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- notes.Notes.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- notes.NotesByCompany.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 500 510 800 admin 910
- notes.NotesByEventType.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- notes.NotesByOwner.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- notes.NotesByPerson.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- notes.NotesByProject.duplicate : visible for 100 110 120 130 200 210 300 400 410 420 430 500 510 800 admin 910
- notes.NotesByType.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- pcsw.AllClients.duplicate : visible for 110 120 410 420 admin 910
- pcsw.Clients.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- pcsw.ClientsByNationality.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910
- pcsw.CoachedClients.duplicate : visible for 100 110 120 130 200 300 400 410 420 430 admin 910
- pcsw.DispenseReasons.duplicate : visible for 110 120 410 420 admin 910
- polls.Choices.duplicate : visible for 110 120 410 420 admin 910
- polls.ChoicesBySet.duplicate : visible for 110 120 410 420 admin 910
- polls.PollResult.duplicate : visible for 110 120 410 420 admin 910
- polls.Questions.duplicate : visible for 110 120 410 420 admin 910
- polls.QuestionsByPoll.duplicate : visible for 100 110 120 130 200 300 400 410 420 430 admin 910
- reception.Clients.duplicate : visible for 100 110 120 130 200 210 220 300 400 410 420 430 500 510 800 admin 910

Permissions

Test whether everybody can display the detail of a client:

>>> o = pcsw.Client.objects.get(id=177)
>>> for u in ('robin', 'alicia', 'theresia', 'caroline', 'kerstin'):
...     print(tostring(rt.login(u).obj2html(o)))
... 
<a href="…">BRECHT Bernd (177)</a>
<a href="…">BRECHT Bernd (177)</a>
<a href="…">BRECHT Bernd (177)</a>
<a href="…">BRECHT Bernd (177)</a>
<a href="…">BRECHT Bernd (177)</a>

Miscellaneous tests

See 2013-05-08:

>>> for model in (debts.Entry,):
...     for o in model.objects.all():
...         o.full_clean()
>>> show_change_watchers()  
+-----------------------+------------------------------+------------------------------------------+
| model                 | master_key                   | ignored_fields                           |
+=======================+==============================+==========================================+
| contacts.Partner      | None                         | address_column contact_details created   |
|                       |                              | created_natural list_item modified       |
|                       |                              | mti_navigator municipality name_column   |
|                       |                              | navigation_panel overview                |
|                       |                              | workflow_buttons                         |
+-----------------------+------------------------------+------------------------------------------+
| contacts.Person       | contacts.Person.partner_ptr  | address_column age contact_details       |
|                       |                              | created created_natural list_item        |
|                       |                              | modified mti_navigator municipality      |
|                       |                              | name_column navigation_panel overview    |
|                       |                              | workflow_buttons                         |
+-----------------------+------------------------------+------------------------------------------+
| contacts.Company      | contacts.Company.partner_ptr | created modified                         |
+-----------------------+------------------------------+------------------------------------------+
| clients.ClientContact | client__partner_ptr          | list_item name_column navigation_panel   |
|                       |                              | overview workflow_buttons                |
+-----------------------+------------------------------+------------------------------------------+
| coachings.Coaching    | client__partner_ptr          | list_item name_column navigation_panel   |
|                       |                              | overview workflow_buttons                |
+-----------------------+------------------------------+------------------------------------------+
| pcsw.Client           | contacts.Person.partner_ptr  | active_contract address_column age       |
|                       |                              | applies_from applies_until               |
|                       |                              | cbss_relations cef_level_de cef_level_en |
|                       |                              | cef_level_fr coaches contact_details     |
|                       |                              | created created_natural eid_info         |
|                       |                              | find_appointment image                   |
|                       |                              | language_knowledge list_item modified    |
|                       |                              | mother_tongues mti_navigator             |
|                       |                              | municipality name_column                 |
|                       |                              | navigation_panel overview primary_coach  |
|                       |                              | workflow_buttons                         |
+-----------------------+------------------------------+------------------------------------------+
| jobs.JobProvider      | contacts.Company.partner_ptr | created modified                         |
+-----------------------+------------------------------+------------------------------------------+
| jobs.Employer         | contacts.Company.partner_ptr | created modified                         |
+-----------------------+------------------------------+------------------------------------------+
| households.Household  | None                         | address_column contact_details created   |
|                       |                              | created_natural list_item modified       |
|                       |                              | mti_navigator municipality name_column   |
|                       |                              | navigation_panel overview                |
|                       |                              | workflow_buttons                         |
+-----------------------+------------------------------+------------------------------------------+

20240906 The following code snippet was used to try to reproduce a mysterious thing that happened to an end user yesterday. The designation of one database row had been copied over that of another, leading to two database rows with the same designation.

>>> rt.login("romain").show(cal.EventTypes)
======================================== ======================================== =============================== ================= ==============================
 Bezeichnung                              Bezeichnung (de)                         Bezeichnung (en)                Klient einladen   Champ FSE
---------------------------------------- ---------------------------------------- ------------------------------- ----------------- ------------------------------
 Absences                                 Abwesenheiten                            Absences                        Nein
 Atelier                                  Atelier                                  Workshop                        Nein
 Consultations avec le bénéficiaire       Beratungen mit Klient                    Consultations with client       Nein
 Informational meetings                   Informational meetings                   Informational meetings          Ja                S.I.S. agréé
 Internal meetings with client            Internal meetings with client            Internal meetings with client   Ja                Séance d’information
 Interne                                  Intern                                   Internal                        Nein
 Jours fériés                             Feiertage                                Holidays                        Nein
 Privé                                    Privat                                   Private                         Nein
 Réunion                                  Versammlung                              Meeting                         Nein
 Réunions externe                         Réunions externe                         External meetings               Nein
 Réunions externes avec le bénéficiaire   Réunions externes avec le bénéficiaire   External meetings with client   Ja                Evaluation formation externe
 Réunions interne                         Réunions interne                         Internal meetings               Nein
 Évaluation                               Auswertung                               Evaluation                      Ja                Entretien individuel
======================================== ======================================== =============================== ================= ==============================