Miscellaneous

This document contains code snippets (lines starting with >>>) that get tested as part of our development workflow.

>>> 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)
>>> demo_get(
...    'rolf', 'api/newcomers/AvailableCoachesByClient', json_fields,
...    2, mt=50, 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)
>>> mt = contenttypes.ContentType.objects.get_for_model(pcsw.Client).pk
>>> 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 420 admin 910
- newcomers.ClientsByFaculty.find_by_beid : visible for 100 110 120 200 210 220 300 400 410 420 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 200 210 220 300 400 410 420 800 admin 910
- pcsw.ClientsByNationality.find_by_beid : visible for 100 110 120 200 210 220 300 400 410 420 800 admin 910
- pcsw.CoachedClients.find_by_beid : visible for 100 110 120 200 300 400 410 420 admin 910
- reception.Clients.find_by_beid : visible for 100 110 120 200 210 220 300 400 410 420 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 200 210 300 400 410 420 500 510 admin 910
- cal.EntriesByClient.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- cal.EntriesByController.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- cal.EntriesByDay.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- cal.EntriesByGuest.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- cal.EntriesByProject.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- cal.EntriesByRoom.duplicate : visible for 100 110 120 200 210 300 400 410 420 500 510 admin 910
- cal.EntriesByType.duplicate : visible for 100 110 120 200 210 300 400 410 420 500 510 admin 910
- cal.EventTypes.duplicate : visible for 110 120 410 420 admin 910
- cal.Events.duplicate : visible for 100 110 120 200 210 300 400 410 420 500 510 admin 910
- cal.MyAssignedEvents.duplicate : visible for 100 110 120 200 300 400 410 420 500 510 admin 910
- cal.MyEntries.duplicate : visible for 100 110 120 200 300 400 410 420 500 510 admin 910
- cal.MyEntriesToday.duplicate : visible for 100 110 120 200 300 400 410 420 500 510 admin 910
- cal.MyOverdueAppointments.duplicate : visible for 100 110 120 200 300 400 410 420 500 510 admin 910
- cal.MyUnconfirmedAppointments.duplicate : visible for 100 110 120 200 300 400 410 420 500 510 admin 910
- cal.OneEvent.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- cal.OverdueAppointments.duplicate : visible for 110 120 410 420 admin 910
- cal.PublicEntries.duplicate : visible for 210
- cal.RemoteCalendars.duplicate : visible for 110 120 410 420 admin 910
- calview.DailyPlanner.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- calview.DailyPlannerRows.duplicate : visible for 110 120 410 420 admin 910
- calview.DailySlave.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 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 200 210 300 400 410 420 admin 910
- cbss.IdentifyRequestsByPerson.duplicate : visible for 100 110 120 200 210 300 400 410 420 admin 910
- cbss.ManageAccessRequests.duplicate : visible for 100 110 120 200 210 300 400 410 420 admin 910
- cbss.ManageAccessRequestsByPerson.duplicate : visible for 100 110 120 200 210 300 400 410 420 admin 910
- cbss.MyIdentifyPersonRequests.duplicate : visible for 100 110 120 200 210 300 400 410 420 admin 910
- cbss.MyManageAccessRequests.duplicate : visible for 100 110 120 200 210 300 400 410 420 admin 910
- cbss.MyRetrieveTIGroupsRequests.duplicate : visible for 100 110 120 200 210 300 400 410 420 admin 910
- cbss.RetrieveTIGroupsRequests.duplicate : visible for 100 110 120 200 210 300 400 410 420 admin 910
- cbss.RetrieveTIGroupsRequestsByPerson.duplicate : visible for 100 110 120 200 210 300 400 410 420 admin 910
- clients.PartnersByClientContactType.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- coachings.CoachingEndings.duplicate : visible for 110 120 210 410 420 admin 910
- contacts.Companies.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- contacts.Partners.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- contacts.PartnersByCity.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- contacts.PartnersByCountry.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- contacts.Persons.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- countries.Places.duplicate : visible for 110 120 210 410 420 800 admin 910
- countries.PlacesByCountry.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- countries.PlacesByPlace.duplicate : visible for 110 120 210 410 420 800 admin 910
- courses.ActiveActivities.duplicate : visible for 100 110 120 200 210 300 400 410 420 800 admin 910
- courses.Activities.duplicate : visible for 100 110 120 200 210 300 400 410 420 800 admin 910
- courses.ActivitiesByLayout.duplicate : visible for 100 110 120 200 210 300 400 410 420 800 admin 910
- courses.ActivitiesByLine.duplicate : visible for 100 110 120 200 210 300 400 410 420 800 admin 910
- courses.ActivitiesBySlot.duplicate : visible for 100 110 120 200 210 300 400 410 420 800 admin 910
- courses.ActivitiesByTeacher.duplicate : visible for 100 110 120 200 210 300 400 410 420 800 admin 910
- courses.ActivitiesByTopic.duplicate : visible for 100 110 120 200 210 300 400 410 420 800 admin 910
- courses.AllActivities.duplicate : visible for admin 910
- courses.ClosedActivities.duplicate : visible for 100 110 120 200 210 300 400 410 420 800 admin 910
- courses.DraftActivities.duplicate : visible for 100 110 120 200 210 300 400 410 420 800 admin 910
- courses.EntriesByTeacher.duplicate : visible for 100 110 120 200 210 300 400 410 420 500 510 admin 910
- courses.InactiveActivities.duplicate : visible for 100 110 120 200 210 300 400 410 420 800 admin 910
- courses.JobCourses.duplicate : visible for 100 110 120 200 210 300 400 410 420 800 admin 910
- courses.Lines.duplicate : visible for 100 110 120 200 210 300 400 410 420 800 admin 910
- courses.LinesByTopic.duplicate : visible for 100 110 120 200 210 300 400 410 420 800 admin 910
- courses.MyActivities.duplicate : visible for 100 110 120 200 210 300 400 410 420 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 200 210 220 300 400 410 420 500 510 800 admin 910
- dashboard.WidgetsByUser.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- debts.Accounts.duplicate : visible for admin 910
- debts.AccountsByGroup.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 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 200 210 220 300 400 410 420 500 510 800 admin 910
- excerpts.ExcerptsByOwner.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- excerpts.ExcerptsByProject.duplicate : visible for 100 110 120 200 210 300 400 410 420 500 510 800 admin 910
- excerpts.ExcerptsByType.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- excerpts.MyExcerpts.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- extensible.PanelEvents.duplicate : visible for 100 110 120 200 300 400 410 420 500 510 admin 910
- households.Households.duplicate : visible for 100 110 120 200 210 300 400 410 420 500 510 800 admin 910
- households.HouseholdsByType.duplicate : visible for 100 110 120 200 210 300 400 410 420 500 510 800 admin 910
- integ.Clients.duplicate : visible for 100 110 120 420 admin 910
- integ.CoachingEndingsByType.duplicate : visible for 110 120 210 410 420 admin 910
- integ.CoachingEndingsByUser.duplicate : visible for 110 120 210 410 420 admin 910
- integ.CompaniesAndContracts.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- integ.JobProvidersAndContracts.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- isip.EntriesByContract.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- jobs.Employers.duplicate : visible for 100 110 120 420 admin 910
- jobs.JobProviders.duplicate : visible for 100 110 120 420 admin 910
- jobs.JobTypes.duplicate : visible for 110 120 410 420 admin 910
- jobs.WorkplacesByProvider.duplicate : visible for 100 110 120 420 admin 910
- linod.SystemTasks.duplicate : visible for admin 910
- newcomers.ClientsByFaculty.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 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 200 210 220 300 400 410 420 500 510 800 admin 910
- newcomers.MyCompetences.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 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 200 210 220 300 400 410 420 500 510 800 admin 910
- notes.Notes.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- notes.NotesByCompany.duplicate : visible for 100 110 120 200 210 300 400 410 420 500 510 800 admin 910
- notes.NotesByEventType.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- notes.NotesByOwner.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- notes.NotesByPerson.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- notes.NotesByProject.duplicate : visible for 100 110 120 200 210 300 400 410 420 500 510 800 admin 910
- notes.NotesByType.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- pcsw.AllClients.duplicate : visible for 110 120 410 420 admin 910
- pcsw.Clients.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- pcsw.ClientsByNationality.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 500 510 800 admin 910
- pcsw.CoachedClients.duplicate : visible for 100 110 120 200 300 400 410 420 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 200 300 400 410 420 admin 910
- reception.Clients.duplicate : visible for 100 110 120 200 210 220 300 400 410 420 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                         |
+-----------------------+------------------------------+------------------------------------------+