.. doctest docs/specs/households.rst .. _welfare.specs.households: .. include:: /../docs/shared/include/defs.rst ========== Households ========== .. currentmodule:: lino_welfare.modlib.households The :mod:`lino_welfare.modlib.households` plugin extends :mod:`lino.modlib.households` by adding some PCSW-specific features. .. contents:: :local: .. include:: /shared/include/tested.rst >>> from lino import startup >>> startup('lino_welfare.projects.gerd.settings.doctests') >>> from lino.api.doctest import * >>> import datetime Added features ============== .. class:: RefundsByPerson Shows the members of the primary household of this person together with an amount which depends on whether that member is adult or not. This is a special form of :class:`lino_xl.lib.households.SiblingsByPerson`, used e.g. in :xfile:`aids/Confirmation/clothes_bank.body.html`. It has two configurable attributes: .. attribute:: child_tariff The amount to refund for children (household members less than :attr:`lino_xl.lib.households.Plugin.adult_age` years old). .. attribute:: adult_tariff The amount to refund for children (household members who are :attr:`lino_xl.lib.households.Plugin.adult_age` years or older). The values of these attributes are hard-coded and defaul to 10 and 20: >>> rt.models.households.RefundsByPerson.child_tariff Decimal('10') >>> rt.models.households.RefundsByPerson.adult_tariff Decimal('20') You might change them locally e.g. in the :attr:`lino.core.site.Site.custom_layouts` module. .. attribute:: person_info The full name of the household member. .. attribute:: amount The amount to pay. This is either :attr:`child_tariff` or :attr:`adult_tarif` depending on the age of the household member. See the examples below. .. function:: get_household_summary(person, today=None, adult_age=None) Return a string which expresses the household composition in a few words. See `The household summary`_. Note that members without `birth_date` are considered children. .. _paulfrisch: Paul Frisch =========== Mr. Paul Frisch is a fictive client for which the demo database contains fictive family links. >>> paul = contacts.Person.objects.get(first_name="Paul", last_name="Frisch") >>> print(paul.id) 240 >>> print(paul) Herr Paul FRISCH His primary household consists of 2 adults and 3 children: >>> print(rt.models.households.get_household_summary(paul)) 2 Erwachsene und 3 Kinder >>> test_client.force_login(rt.login('rolf').user) >>> def check(uri, fieldname): ... url = '/api/%s?fmt=json&an=detail' % uri ... res = test_client.get(url, REMOTE_USER='rolf') ... assert res.status_code == 200 ... d = json.loads(res.content) ... if not fieldname in d['data']: ... raise Exception("20181023 '{}' not in {}".format( ... fieldname, d['data'].keys())) ... return d['data'][fieldname] >>> uri = 'contacts/Persons/{}'.format(paul.id) >>> html = check(uri, 'humanlinks_LinksByHuman') >>> soup = BeautifulSoup(html, 'lxml') >>> links = soup.find_all('a') >>> len(links) 23 >>> print(links[1].get('href')) ... #doctest: +NORMALIZE_WHITESPACE javascript:Lino.contacts.Persons.detail.run(null,{ "record_id": 248 }) These are the family relationships of Paul Frisch: >>> print(soup.get_text(' ', strip=True)) ... #doctest: +NORMALIZE_WHITESPACE +REPORT_CDIFF Paul ist Vater von Dennis (12 Jahre) Vater von Clara (14 Jahre) Vater von Philippe (16 Jahre) Vater von Peter (26 Jahre) Ehemann von Petra ZWEITH (45 Jahre) Sohn von Gaby FROGEMUTH (79 Jahre) Sohn von Hubert (80 Jahre) Beziehung erstellen als Vater / Sohn Adoptivvater / Adoptivsohn Pflegevater / Pflegesohn Ehemann Partner Stiefvater / Stiefsohn Bruder Vetter Onkel / Neffe Verwandter Sonstiger The previous AJAX call caused Django's translation machine to switch to German. Switch back to English. >>> translation.activate('en') Paul's father Hubert is married with Gaby and they live together. Their children have moved out. >>> obj = contacts.Person.objects.get(name="Frisch Hubert") >>> print(obj) Mr Hubert FRISCH >>> ses = rt.login('rolf') >>> ses.show(households.SiblingsByPerson, master_instance=obj) ========== =================== =============== ==================== ============ =========== ============ ======== Age Role Dependency Person First name Last name Birth date Gender ---------- ------------------- --------------- -------------------- ------------ ----------- ------------ -------- 80 years Head of household Not at charge Mr Hubert FRISCH Hubert Frisch 1933-07-21 Male 79 years Partner Not at charge Mrs Gaby FROGEMUTH Gaby Frogemuth 1934-08-04 Female ========== =================== =============== ==================== ============ =========== ============ ======== Paul Frisch is married with Petra Zweith and has a child from divorced marriage with Paula Einzig. >>> obj = contacts.Person.objects.get(name="Frisch Paul") >>> print(obj) Mr Paul FRISCH >>> ses.show(households.SiblingsByPerson, master_instance=obj) ========== =================== ================ ==================== ============ =========== ============ ======== Age Role Dependency Person First name Last name Birth date Gender ---------- ------------------- ---------------- -------------------- ------------ ----------- ------------ -------- 46 years Head of household Not at charge Mr Paul FRISCH Paul Frisch 1967-06-19 Male 45 years Partner Not at charge Mrs Petra ZWEITH Petra Zweith 1968-12-19 Female 16 years Child At full charge Mr Philippe FRISCH Philippe Frisch 1997-06-19 Male 14 years Child At full charge Mrs Clara FRISCH Clara Frisch 1999-06-19 Female 12 years Child At full charge Mr Dennis FRISCH Dennis Frisch 2001-06-19 Male ========== =================== ================ ==================== ============ =========== ============ ======== >>> ses.show(households.RefundsByPerson, master_instance=obj) ========== ======== ==================== =========== Age Gender Person Amount ---------- -------- -------------------- ----------- 46 years Male Paul FRISCH 20,00 45 years Female Petra ZWEITH 20,00 16 years Male Philippe FRISCH 10,00 14 years Female Clara FRISCH 10,00 12 years Male Dennis FRISCH 10,00 **Total (5 rows)** **70,00** ========== ======== ==================== =========== Ludwig Frisch is married with Laura Loslever and they live together with their two children. >>> obj = contacts.Person.objects.get(name="Frisch Ludwig") >>> print(obj) Mr Ludwig FRISCH >>> ses.show(households.SiblingsByPerson, master_instance=obj) ========== =================== ================ ==================== ============ =========== ============ ======== Age Role Dependency Person First name Last name Birth date Gender ---------- ------------------- ---------------- -------------------- ------------ ----------- ------------ -------- 46 years Partner Not at charge Mrs Laura LOSLEVER Laura Loslever 1968-04-27 Female 45 years Head of household Not at charge Mr Ludwig FRISCH Ludwig Frisch 1968-06-01 Male 12 years Child At full charge Mrs Melba FRISCH Melba Frisch 2002-04-05 Female 6 years Child At full charge Mrs Irma FRISCH Irma Frisch 2008-03-24 Female ========== =================== ================ ==================== ============ =========== ============ ======== Here is what Ludwig's LinksByHuman panel shows: >>> ses.show(humanlinks.LinksByHuman, master_instance=obj) Ludwig is Father of `Irma `__ (6 years) Father of `Melba `__ (12 years) Husband of `Laura LOSLEVER `__ (46 years) Son of `Gaby FROGEMUTH `__ (79 years) Son of `Hubert `__ (80 years) Create relationship as **Father**/**Son** **Adoptive father**/**Adopted son** **Foster father**/**Foster son** **Husband** **Partner** **Stepfather**/**Stepson** **Brother** **Cousin** **Uncle**/**Nephew** **Relative** **Other** Here is his :class:`RefundsByPerson` table: >>> ses.show(households.RefundsByPerson, master_instance=obj) ========== ======== ==================== =========== Age Gender Person Amount ---------- -------- -------------------- ----------- 46 years Female Laura LOSLEVER 20,00 45 years Male Ludwig FRISCH 20,00 12 years Female Melba FRISCH 10,00 6 years Female Irma FRISCH 10,00 **Total (4 rows)** **60,00** ========== ======== ==================== =========== An edge case ============ The following edge case failed before 20170206: >>> ses.show(humanlinks.LinksByHuman) .. _welfare.specs.households.20190326: Melba getting adult =================== The :class:`RefundsByPerson` table depends on the current date, which is 2014-05-22 for this demo: >>> dd.today() datetime.date(2014, 5, 22) The demo date is stored in a site attribute :attr:`the_demo_date `: >>> settings.SITE.the_demo_date datetime.date(2014, 5, 22) Let's have a look at Ludwig's :class:`RefundsByPerson` table when Melba gets adult. The default configuration says that you get adult at 18: >>> dd.plugins.households.adult_age 18 In 2019 Melba is 17, still a child: >>> settings.SITE.the_demo_date = datetime.date(2019, 5, 22) >>> ses.show(households.RefundsByPerson, master_instance=obj) ========== ======== ==================== =========== Age Gender Person Amount ---------- -------- -------------------- ----------- 51 years Female Laura LOSLEVER 20,00 50 years Male Ludwig FRISCH 20,00 17 years Female Melba FRISCH 10,00 11 years Female Irma FRISCH 10,00 **Total (4 rows)** **60,00** ========== ======== ==================== =========== But in 2020 she is 18, now her refunded amount is that of an adult: >>> settings.SITE.the_demo_date = datetime.date(2020, 5, 22) >>> ses.show(households.RefundsByPerson, master_instance=obj) ========== ======== ==================== =========== Age Gender Person Amount ---------- -------- -------------------- ----------- 52 years Female Laura LOSLEVER 20,00 51 years Male Ludwig FRISCH 20,00 18 years Female Melba FRISCH 20,00 12 years Female Irma FRISCH 10,00 **Total (4 rows)** **70,00** ========== ======== ==================== =========== Note: Before 20190326 above table gave an amount of 10,00 for Melba because of a bug (you got adult only one year after the age specified in :attr:`lino_xl.lib.households.Plugin.adult_age`). For the following tests we set :attr:`the_demo_date ` back to its original value: >>> settings.SITE.the_demo_date = datetime.date(2014, 5, 22) Inspecting the MembersByPerson panel ==================================== The following code caused an exception "ParameterStore of LayoutHandle for ParamsLayout on pcsw.Clients expects a list of 12 values but got 16" on :blogref:`20140429`. >>> print(pcsw.Client.objects.get(pk=179)) DUBOIS Robin (179) >>> print(len(integ.Clients.params_layout.get_layout_handle()._store_fields)) 16 >>> url = '/api/integ/Clients/179?' >>> url += 'pv=30&pv=5&pv=&pv=29.04.2014&pv=29.04.2014&pv=&pv=&pv=&pv=&pv=&pv=false&pv=&pv=&pv=1&pv=false&pv=false' >>> url += '&an=detail&rp=ext-comp-1351&fmt=json' >>> res = test_client.get(url, REMOTE_USER='rolf') >>> print(res.status_code) 200 The response to this AJAX request is in JSON: >>> d = json.loads(res.content) We test the MembersByPerson panel. It contains a summary: >>> print(d['data']['households_MembersByPerson']) ... #doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
DUBOIS Robin (179) ist