Merge remote-tracking branch 'origin/master' into rector/rules-up-to-php80

Conflicts:
	src/Bundle/ChillActivityBundle/Controller/ActivityController.php
	src/Bundle/ChillActivityBundle/Export/Aggregator/ACPAggregators/DateAggregator.php
	src/Bundle/ChillActivityBundle/Menu/PersonMenuBuilder.php
	src/Bundle/ChillActivityBundle/Repository/ActivityACLAwareRepository.php
	src/Bundle/ChillActivityBundle/Service/DocGenerator/ActivityContext.php
	src/Bundle/ChillCalendarBundle/Command/MapAndSubscribeUserCalendarCommand.php
	src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/MSGraphUserRepository.php
	src/Bundle/ChillDocStoreBundle/Controller/DocumentAccompanyingCourseController.php
	src/Bundle/ChillDocStoreBundle/Controller/DocumentPersonController.php
	src/Bundle/ChillDocStoreBundle/Repository/PersonDocumentACLAwareRepository.php
	src/Bundle/ChillEventBundle/Search/EventSearch.php
	src/Bundle/ChillMainBundle/Controller/ExportController.php
	src/Bundle/ChillMainBundle/Controller/PermissionsGroupController.php
	src/Bundle/ChillMainBundle/Cron/CronManager.php
	src/Bundle/ChillMainBundle/Entity/CronJobExecution.php
	src/Bundle/ChillMainBundle/Export/ExportManager.php
	src/Bundle/ChillMainBundle/Form/Type/Export/PickCenterType.php
	src/Bundle/ChillMainBundle/Form/Type/Listing/FilterOrderType.php
	src/Bundle/ChillMainBundle/Repository/NotificationRepository.php
	src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelper.php
	src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperBuilder.php
	src/Bundle/ChillMainBundle/Templating/Listing/FilterOrderHelperFactory.php
	src/Bundle/ChillPersonBundle/Controller/AccompanyingCourseWorkController.php
	src/Bundle/ChillPersonBundle/Controller/SocialWorkSocialActionApiController.php
	src/Bundle/ChillPersonBundle/Export/Aggregator/PersonAggregators/AgeAggregator.php
	src/Bundle/ChillPersonBundle/Export/Export/ListAccompanyingPeriod.php
	src/Bundle/ChillPersonBundle/Export/Export/ListHouseholdInPeriod.php
	src/Bundle/ChillPersonBundle/Repository/AccompanyingPeriodACLAwareRepository.php
	src/Bundle/ChillPersonBundle/Security/Authorization/AccompanyingPeriodVoter.php
	src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodContext.php
	src/Bundle/ChillPersonBundle/Service/DocGenerator/AccompanyingPeriodWorkEvaluationContext.php
	src/Bundle/ChillPersonBundle/Service/DocGenerator/PersonContext.php
	src/Bundle/ChillReportBundle/DataFixtures/ORM/LoadReports.php
	src/Bundle/ChillTaskBundle/Controller/SingleTaskController.php
This commit is contained in:
2023-07-17 12:49:13 +02:00
544 changed files with 18622 additions and 2105 deletions

View File

@@ -62,7 +62,6 @@ class BirthdateFilter implements ExportElementValidatedInterface, FilterInterfac
{
$builder->add('date_from', DateType::class, [
'label' => 'Born after this date',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
@@ -70,12 +69,15 @@ class BirthdateFilter implements ExportElementValidatedInterface, FilterInterfac
$builder->add('date_to', DateType::class, [
'label' => 'Born before this date',
'data' => new DateTime(),
'attr' => ['class' => 'datepicker'],
'widget' => 'single_text',
'format' => 'dd-MM-yyyy',
]);
}
public function getFormDefaultData(): array
{
return ['date_from' => new DateTime(), 'date_to' => new DateTime()];
}
// here, we create a simple string which will describe the action of
// the filter in the Response

View File

@@ -36,6 +36,10 @@ class CountPerson implements ExportInterface
{
// this export does not add any form
}
public function getFormDefaultData(): array
{
return [];
}
public function getAllowedFormattersTypes()
{

View File

@@ -0,0 +1,84 @@
.. database-principles:
Principes de la base de données
###############################
Cette page donne une compréhension globale de la base de donnée de Chill, et explique quelques détails d'implémentations qui permettent d'accélérer les traitements à partir de la base de donnée, ou de l'exploiter plus aisément.
Cette page est rédigée en français.
.. note::
La stabilité du schéma de la base de donnée n'est pas garantie.
Toutefois, ce dernier évolue relativement peu. Il est rare que des tables ou des colonnes soient supprimées ou renommées. Mais il n'est pas garanti que cela puisse arriver.
Généralités
===========
Une liste commentée de toutes les tables :download:`est disponible au format CSV <./database/table_list.csv`.
Schéma et conventions de nommage
--------------------------------
Au début de l'histoire de Chill, les schémas postgresql n'étaient pas exploités. Les données étaient stockées dans le schéma :code:`public`.
Par la suite, des nouveaux bundles sont apparus, et les tables ont été classées dans des schémas dédiés.
A l'heure actuelle:
- pour les anciens bundle, ceux qui ont déjà des tables dans le schéma public, les nouvelles tables sont ajoutées à ce schéma. Elles sont préfixées par :code:`chill_<nom du bundle>_`;
- pour les bundles plus récents, les tables sont créées dans le schéma dédié
Données avec de l'historicité
-----------------------------
Certaines données sont historisées:
- les référents d'un parcours;
- les statuts d'un parcours;
- la liaison entre les centres et les usagers;
- etc.
Dans ces cas-là, Chill crée généralement deux colonnes, qui sont habituellement nommées :code:`startDate` et :code:`endDate`. Lorsque la colonne :code:`endDate` est à :code:`NULL`, cela signifie que la période n'est pas "fermée". La colonne :code:`startDate` n'est pas nullable.
Dans certains cas, la donnée actuelle (référent d'un parcours, par exemple) est également répétée au niveau de la table en elle-même. Par exemple, la table des parcours :code:`chill_person_accompanying_period` comporte une colonne :code:`step` (le statut du parcours) et :code:`user_id` (id du référent) en plus de l'historique. Bien que redondant, cela simplifie les traitements.
Relations particulières
=======================
Usagers, ménages, adresses
--------------------------
Les usagers ont une adresse au travers des ménages: dans l'interface, l'adresse est inscrite dans le dossier du ménage, et elle est "donnée" aux usagers membres du ménage, **et** qui partagent l'adresse de ce ménage. En effet, il est possible que des usagers "appartiennent" à un ménage sans y être domicilié: c'est le cas, par exemple, des enfants en garde alternée.
L'historique de l'appartenance des usagers au ménage est conservée, de même que l'historique des adresses pour un même ménage.
Les tables en jeu sont les suivantes:
- la table :code:`chill_person_person` liste les usagers;
- la table :code:`chill_person_household_members` liste les appartenances au ménage: il s'agit de la jointure entre les usagers et les ménages:
- les colonnes :code:`startDate` et :code:`endDate` indiquent la date de début et la date de fin de l'appartenance;
- la colonne :code:`shareHousehold` indique si l'utilisateur partage l'adresse du ménage (si oui, sa valeur est :code:`TRUE`)
- la table :code:`chill_person_household` liste les ménages
- la table :code:`chill_person_household_to_addresses` associe les ménages aux adresses;
- la table :code:`chill_main_address` contient les adresses, en indiquant la date de début de validité (:code:`validFrom`) et la fin de validité (:code:`validTo`).
Pour simplifier la résolution des adresses et des usagers, deux vues ont été mises en œuvre:
- la vue :code:`view_chill_person_household_address` reprend, pour chaque usager, l'historique des appartenances au ménage découpée par l'historique des adresses d'un ménage.
Autrement dit, une ligne est créée à chaque fois qu'un usager change de ménage, ou qu'un ménage change d'adresse. Il est donc possible de retrouver l'historique complet des adresses pour un usager donné via cette table.
- la vue :code:`view_chill_person_current_address` reprend l'adresse actuelle des usagers.
Adresses et unités géographiques
--------------------------------
Chill propose des statistiques sur la localisation des adresses par rapport à des zones géographiques (:code:`chill_main_geographical_unit`).
Comme la résolution géographique des adresses est coûteuse en CPU et en temps de traitement, une vue matérialisée a été créée: :code:`view_chill_main_address_geographical_unit`. Elle est rafraichie quotidiennement dans la base de donnée de production.
Liste des tables et commentaires
================================
Une liste commentée de toutes les tables :download:`est disponible au format CSV <./database/table_list.csv`.

View File

@@ -0,0 +1,155 @@
order,table_schema,table_name,commentaire
1,chill_3party,party_category,Catégorie de tiers
2,chill_3party,party_center,Association entre les tiers et les centres (déprécié)
3,chill_3party,party_profession,Profession du tiers (déprécié)
4,chill_3party,third_party,Tiers
5,chill_3party,thirdparty_category,association tiers - catégories
6,chill_asideactivity,asideactivity,Activités annexes
7,chill_asideactivity,asideactivitycategory,Catégories d'activités annexes
8,chill_budget,charge,Charges du budget
9,chill_budget,charge_type,Types de charges
10,chill_budget,resource,Ressources du budget
11,chill_budget,resource_type,Types de ressources
12,chill_calendar,calendar,Rendez-vous
13,chill_calendar,calendar_doc,Document du rendez-vous
14,chill_calendar,calendar_range,Plage de disponibilité
15,chill_calendar,calendar_to_persons,association rendez-vous - usagers
16,chill_calendar,calendar_to_thirdparties,association rendez-vous - tiers
17,chill_calendar,cancel_reason,Motifs d'annulations
18,chill_calendar,invite,Invitation aux rendez-vous
19,chill_doc,accompanyingcourse_document,Documents associés aux parcours
20,chill_doc,document_category,Catégories de documents
21,chill_doc,person_document,Documents associés à l'usagers
22,chill_doc,stored_object,Documents
23,chill_task,recurring_task,Tâches récurrentes (non utilisé)
24,chill_task,single_task,Tâches
25,chill_task,single_task_place_event,Historique des transitions des tâches
26,chill_vendee,adressederelais,
27,chill_vendee,center_polygon
28,chill_vendee,entourage,
29,chill_vendee,geographical_unit
30,chill_vendee,geographical_unit_association
31,chill_vendee,mobilite
32,chill_vendee,niveauetude
33,chill_vendee,security_profile
34,chill_vendee,security_profile_action
35,chill_vendee,security_profile_jobs
36,chill_vendee,situationprofessionelle
37,chill_vendee,statutlogement
38,chill_vendee,tempsdetravail
39,chill_vendee,titredesejour
40,chill_vendee,vendee_person
41,chill_vendee,vendee_person_mineur
42,chill_vendee,vendeeperson_entourage
43,chill_vendee,vendeepersonmineur_adressederelais
44,public,accompanying_periods_scopes,Services associés aux parcours
45,public,activity,Échanges
46,public,activity_activityreason,s
47,public,activity_person,
48,public,activity_storedobject,
49,public,activity_thirdparty,
50,public,activity_user,
51,public,activityreason,Sujets d'échange
52,public,activityreasoncategory,Catégories de sujets
53,public,activitytpresence,Présence aux échanges
54,public,activitytype,Types d'échanges
55,public,activitytypecategory,Catégories de types d'échanges
56,public,centers,"Centres (territoires, agences, etc.)"
57,public,chill_activity_activity_chill_person_socialaction,
58,public,chill_activity_activity_chill_person_socialissue
59,public,chill_docgen_template,Gabarits de documents
60,public,chill_main_address,Adresses
61,public,chill_main_address_legacy,Anciennes adresses (dépréciés)
62,public,chill_main_address_reference,Adresses de référence
63,public,chill_main_civility,Civilités
64,public,chill_main_cronjob_execution,Dernière exécution des tâche cron
65,public,chill_main_geographical_unit,Unités géographiques
66,public,chill_main_geographical_unit_layer,Couches d'unités géographiques
67,public,chill_main_location,Localisations
68,public,chill_main_location_type,Types de localisations
69,public,chill_main_notification,Notifications
70,public,chill_main_notification_addresses_unread
71,public,chill_main_notification_addresses_user
72,public,chill_main_notification_comment,
73,public,chill_main_postal_code,Code postaux
74,public,chill_main_saved_export,Exports enregistrés
75,public,chill_main_user_job,Métiers
76,public,chill_main_workflow_entity,Workflows
77,public,chill_main_workflow_entity_comment
78,public,chill_main_workflow_entity_step,Etapes du workflow
79,public,chill_main_workflow_entity_step_cc_user,
80,public,chill_main_workflow_entity_step_user
81,public,chill_main_workflow_entity_step_user_by_accesskey,
82,public,chill_main_workflow_entity_subscriber_to_final,
83,public,chill_main_workflow_entity_subscriber_to_step
84,public,chill_person_accompanying_period,Parcours d'accompagnement
85,public,chill_person_accompanying_period_closingmotive,Motifs de cloture des parcours
86,public,chill_person_accompanying_period_comment,Commentaires des parcours
87,public,chill_person_accompanying_period_location_history,Historique de la localisatio ndes parcours
88,public,chill_person_accompanying_period_origin,Origine des parcours
89,public,chill_person_accompanying_period_participation,Appartenance des usagers au parcours
90,public,chill_person_accompanying_period_resource,Personnes ressources d'un parcours
91,public,chill_person_accompanying_period_social_issues,
92,public,chill_person_accompanying_period_step_history
93,public,chill_person_accompanying_period_user_history
94,public,chill_person_accompanying_period_work,Actions d'accompagnements
95,public,chill_person_accompanying_period_work_evaluation,Évaluations (dans les actions d'accompagnements)
96,public,chill_person_accompanying_period_work_evaluation_document,Documents des évaluations
97,public,chill_person_accompanying_period_work_goal,Objectifs d'une actions
98,public,chill_person_accompanying_period_work_goal_result,Objectifs et résultats d'une action
99,public,chill_person_accompanying_period_work_person,Usagers associés à une actions
100,public,chill_person_accompanying_period_work_referrer,Référents d'une actions
101,public,chill_person_accompanying_period_work_result,Résultats d'une action
102,public,chill_person_accompanying_period_work_third_party,Tiers traitants d'une action
103,public,chill_person_alt_name,"Noms supplémentaires d'un usager (nom marital, etc.)"
104,public,chill_person_household,Ménages
105,public,chill_person_household_composition,
106,public,chill_person_household_composition_type,Types de composition de ménage
107,public,chill_person_household_members,Membres du ménages
108,public,chill_person_household_position,Positions dans le ménage
109,public,chill_person_household_to_addresses,Association adresses - ménages
110,public,chill_person_marital_status,Etats civils
111,public,chill_person_not_duplicate,
112,public,chill_person_person,Usagers
113,public,chill_person_person_center_history,Historique des centres d'un usagers
114,public,chill_person_persons_to_addresses,Déprécié
115,public,chill_person_phone,Numéros d etéléphone supplémentaires d'un usager
116,public,chill_person_relations,Types de relations de filiation
117,public,chill_person_relationships,Relations de filiations
118,public,chill_person_residential_address,Adresses de résidences
119,public,chill_person_resource,Personnes ressources (pour les personnes)
120,public,chill_person_resource_kind,Type de personnes ressources
121,public,chill_person_social_action,Liste des actions d'accompagnement
122,public,chill_person_social_action_goal,Objectifs associés à une action
123,public,chill_person_social_action_result,Résultats associés à une action
124,public,chill_person_social_issue,Problématiques sociales
125,public,chill_person_social_work_evaluation,Evaluations disponibles
126,public,chill_person_social_work_evaluation_action,Associations entre les évaluations et les actions
127,public,chill_person_social_work_goal,Objectifs disponibles pour une actions
128,public,chill_person_social_work_goal_result,Objectifs et résultats disponible pour une action
129,public,chill_person_social_work_result,Résultats disponibles pour une action
130,public,country,Pays
131,public,custom_field_long_choice_options,
132,public,customfield
133,public,customfieldsdefaultgroup
134,public,customfieldsgroup
135,public,geography_columns,Table liée à postgis
136,public,geometry_columns,Table liée à postgis
137,public,group_centers,
138,public,language,Langues
139,public,messenger_messages,Table système
140,public,migration_versions,Table système
141,public,permission_groups
142,public,permissionsgroup_rolescope
143,public,persons_spoken_languages
144,public,regroupment,Regroupement de centres
145,public,regroupment_center,
146,public,role_scopes,
147,public,scopes,Services
148,public,spatial_ref_sys,Table système (postgis)
149,public,user_groupcenter,
150,public,users,Utilisateurs
151,public,view_chill_person_accompanying_period_info,
152,public,view_chill_person_current_address
153,public,view_chill_person_household_address
154,public,view_chill_person_person_center_history_current
Can't render this file because it has a wrong number of fields in line 28.

View File

@@ -0,0 +1,203 @@
.. Copyright (C) 2014 Champs Libres Cooperative SCRLFS
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the section entitled "GNU
Free Documentation License".
.. _entity-info:
Stats about event on entity in php world
########################################
It is necessary to be able to gather information about events for some entities:
- when the event has been done;
- who did it;
- ...
Those "infos" are not linked with right management, like describe in :ref:`timelines`.
“infos” for some stats and info about an entity
-----------------------------------------------
Building an info means:
- create an Entity, and map this entity to a SQL view (not a regular table);
- use the framework to build this entity dynamically.
A framework api is built to be able to build multiple “infos” entities
through “union” views:
- use a command ``bin/console chill:db:sync-views`` to synchronize view (create view if it does not exists, or update
views when new SQL parts are added in the UNION query. Internally, this command call a new ``ViewEntityInfoManager``,
which iterate over available views to build the SQL;
- one can create a new “view entity info” by implementing a
``ViewEntityInfoProviderInterface``
- this implementation of the interface is free to create another
interface for building each part of the UNION query. This interface
is created for AccompanyingPeriodInfo:
``Chill\PersonBundle\Service\EntityInfo\AccompanyingPeriodInfoUnionQueryPartInterface``
So, converting new “events” into rows for ``AccompanyingPeriodInfo`` is
just implementing this interface!
Implementation for AccompanyingPeriod (``AccompanyingPeriod/AccompanyingPeriodInfo``)
-------------------------------------------------------------------------------------
A class is created for computing some statistical info for an
AccompanyingPeriod: ``AccompanyingPeriod/AccompanyingPeriodInfo``. This
contains information about “something happens”, who did it and when.
Having those info in table answer some questions like:
- when is the last and the first action (AccompanyingPeriodWork,
Activity, AccompanyingPeriodWorkEvaluation, …) on the period;
- who is “acting” on the period, and when is the last “action” for each
user.
The AccompanyingPeriod info is mapped to a SQL view, not a table. The
sql view is built dynamically (see below), and gather infos from
ActivityBundle, PersonBundle, CalendarBundle, … It is possible to create
custom bundle and add info on this view.
.. code:: php
/**
*
* @ORM\Entity()
* @ORM\Table(name="view_chill_person_accompanying_period_info") <==== THIS IS A VIEW, NOT A TABLE
*/
class AccompanyingPeriodInfo
{
// ...
}
Why do we need this ?
~~~~~~~~~~~~~~~~~~~~~
For multiple jobs in PHP world:
- moving the accompanying period to another steps when inactive,
automatically;
- listing all the users which are intervening on the action on a new
“Liste des intervenants” page;
- filtering on exports
Later, we will launch automatic anonymise for accompanying period and
all related entities through this information.
How is built the SQL views which is mapped to “info” entities ?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The AccompanyingPeriodInfo entity is mapped by a SQL view (not a regular
table).
The sql view is built dynamically, it is a SQL view like this, for now (April 2023):
.. code:: sql
create view view_chill_person_accompanying_period_info
(accompanyingperiod_id, relatedentity, relatedentityid, user_id, infodate, discriminator, metadata) as
SELECT w.accompanyingperiod_id,
'Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork'::text AS relatedentity,
w.id AS relatedentityid,
cpapwr.user_id,
w.enddate AS infodate,
'accompanying_period_work_end'::text AS discriminator,
'{}'::jsonb AS metadata
FROM chill_person_accompanying_period_work w
LEFT JOIN chill_person_accompanying_period_work_referrer cpapwr ON w.id = cpapwr.accompanyingperiodwork_id
WHERE w.enddate IS NOT NULL
UNION
SELECT cpapw.accompanyingperiod_id,
'Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation'::text AS relatedentity,
e.id AS relatedentityid,
e.updatedby_id AS user_id,
e.updatedat AS infodate,
'accompanying_period_work_evaluation_updated_at'::text AS discriminator,
'{}'::jsonb AS metadata
FROM chill_person_accompanying_period_work_evaluation e
JOIN chill_person_accompanying_period_work cpapw ON cpapw.id = e.accompanyingperiodwork_id
WHERE e.updatedat IS NOT NULL
UNION
SELECT cpapw.accompanyingperiod_id,
'Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation'::text AS relatedentity,
e.id AS relatedentityid,
cpapwr.user_id,
e.maxdate AS infodate,
'accompanying_period_work_evaluation_start'::text AS discriminator,
'{}'::jsonb AS metadata
FROM chill_person_accompanying_period_work_evaluation e
JOIN chill_person_accompanying_period_work cpapw ON cpapw.id = e.accompanyingperiodwork_id
LEFT JOIN chill_person_accompanying_period_work_referrer cpapwr ON cpapw.id = cpapwr.accompanyingperiodwork_id
WHERE e.maxdate IS NOT NULL
UNION
SELECT cpapw.accompanyingperiod_id,
'Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation'::text AS relatedentity,
e.id AS relatedentityid,
cpapwr.user_id,
e.startdate AS infodate,
'accompanying_period_work_evaluation_start'::text AS discriminator,
'{}'::jsonb AS metadata
FROM chill_person_accompanying_period_work_evaluation e
JOIN chill_person_accompanying_period_work cpapw ON cpapw.id = e.accompanyingperiodwork_id
LEFT JOIN chill_person_accompanying_period_work_referrer cpapwr ON cpapw.id = cpapwr.accompanyingperiodwork_id
UNION
SELECT cpapw.accompanyingperiod_id,
'Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument'::text AS relatedentity,
doc.id AS relatedentityid,
doc.updatedby_id AS user_id,
doc.updatedat AS infodate,
'accompanying_period_work_evaluation_document_updated_at'::text AS discriminator,
'{}'::jsonb AS metadata
FROM chill_person_accompanying_period_work_evaluation_document doc
JOIN chill_person_accompanying_period_work_evaluation e ON doc.accompanyingperiodworkevaluation_id = e.id
JOIN chill_person_accompanying_period_work cpapw ON cpapw.id = e.accompanyingperiodwork_id
WHERE doc.updatedat IS NOT NULL
UNION
SELECT cpapw.accompanyingperiod_id,
'Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation'::text AS relatedentity,
e.id AS relatedentityid,
cpapwr.user_id,
e.maxdate AS infodate,
'accompanying_period_work_evaluation_max'::text AS discriminator,
'{}'::jsonb AS metadata
FROM chill_person_accompanying_period_work_evaluation e
JOIN chill_person_accompanying_period_work cpapw ON cpapw.id = e.accompanyingperiodwork_id
LEFT JOIN chill_person_accompanying_period_work_referrer cpapwr ON cpapw.id = cpapwr.accompanyingperiodwork_id
WHERE e.maxdate IS NOT NULL
UNION
SELECT w.accompanyingperiod_id,
'Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork'::text AS relatedentity,
w.id AS relatedentityid,
cpapwr.user_id,
w.startdate AS infodate,
'accompanying_period_work_start'::text AS discriminator,
'{}'::jsonb AS metadata
FROM chill_person_accompanying_period_work w
LEFT JOIN chill_person_accompanying_period_work_referrer cpapwr ON w.id = cpapwr.accompanyingperiodwork_id
UNION
SELECT activity.accompanyingperiod_id,
'Chill\ActivityBundle\Entity\Activity'::text AS relatedentity,
activity.id AS relatedentityid,
au.user_id,
activity.date AS infodate,
'activity_date'::text AS discriminator,
'{}'::jsonb AS metadata
FROM activity
LEFT JOIN activity_user au ON activity.id = au.activity_id
WHERE activity.accompanyingperiod_id IS NOT NULL;
As you can see, the view gather multiple SELECT queries and bind them
with UNION.
Each SELECT query is built dynamically, through a class implementing an
interface: ``Chill\PersonBundle\Service\EntityInfo\AccompanyingPeriodInfoUnionQueryPartInterface``, `like
here <https://gitlab.com/Chill-Projet/chill-bundles/-/blob/master/src/Bundle/ChillPersonBundle/Service/EntityInfo/AccompanyingPeriodInfoQueryPart/AccompanyingPeriodWorkEndQueryPartForAccompanyingPeriodInfo.php>`__
To add new `SELECT` query in different `UNION` parts in the sql view, create a
service and implements this interface: ``Chill\PersonBundle\Service\EntityInfo\AccompanyingPeriodInfoUnionQueryPartInterface``.

View File

@@ -35,6 +35,8 @@ As Chill rely on the `symfony <http://symfony.com>`_ framework, reading the fram
manual/index.rst
Assets <assets.rst>
Cron Jobs <cronjob.rst>
Info about entities <entity-info.rst>
Info about database (in French) <database-principles.rst>
Layout and UI
**************

View File

@@ -6,6 +6,8 @@
A copy of the license is included in the section entitled "GNU
Free Documentation License".
.. _timelines:
Timelines
*********
@@ -18,24 +20,24 @@ Concept
From an user point of view
--------------------------
Chill has two objectives :
Chill has two objectives :
* make the administrative tasks more lightweight ;
* help social workers to have all information they need to work
To reach this second objective, Chill provides a special view: **timeline**. On a timeline view, information is gathered and shown on a single page, from the most recent event to the oldest one.
The information gathered is linked to a *context*. This *context* may be, for instance :
The information gathered is linked to a *context*. This *context* may be, for instance :
* a person : events linked to this person are shown on the page ;
* a center: events linked to a center are shown. They may concern different peoples ;
* ...
* ...
In other word, the *context* is the kind of argument that will be used in the event's query.
Let us recall that only the data the user has allowed to see should be shown.
.. seealso::
.. seealso::
`The issue where the subject was first discussed <https://redmine.champs-libres.coop/issues/224>`_
@@ -43,30 +45,30 @@ Let us recall that only the data the user has allowed to see should be shown.
For developers
--------------
The `Main` bundle provides interfaces and services to help to build timelines.
The `Main` bundle provides interfaces and services to help to build timelines.
If a bundle wants to *push* information in a timeline, it should be create a service which implements `Chill\MainBundle\Timeline\TimelineProviderInterface`, and tag is with `chill.timeline` and arguments defining the supported context (you may use multiple `chill.timeline` tags in order to support multiple context with a single service/class).
If a bundle wants to provide a new context for a timeline, the service `chill.main.timeline_builder` will helps to gather timeline's services supporting the defined context, and run queries across the models.
If a bundle wants to provide a new context for a timeline, the service `chill.main.timeline_builder` will helps to gather timeline's services supporting the defined context, and run queries across the models.
.. _understanding-queries :
Understanding queries
^^^^^^^^^^^^^^^^^^^^^
Due to the fact that timelines should show only the X last events from Y differents tables, queries for a timeline may consume a lot of resources: at first on the database, and then on the ORM part, which will have to deserialize DB data to PHP classes, which may not be used if they are not part of the "last X events".
Due to the fact that timelines should show only the X last events from Y differents tables, queries for a timeline may consume a lot of resources: at first on the database, and then on the ORM part, which will have to deserialize DB data to PHP classes, which may not be used if they are not part of the "last X events".
To avoid such load on database, the objects are queried in two steps :
To avoid such load on database, the objects are queried in two steps :
1. An UNION request which gather the last X events, ordered by date. The data retrieved are the ID, the date, and a string key: a type. This type discriminates the data type.
2. The PHP objects are queried by ID, the type helps the program to link id with the kind of objects.
2. The PHP objects are queried by ID, the type helps the program to link id with the kind of objects.
Those methods should ensure that only X PHP objects will be gathered and build by the ORM.
What does the master timeline builder service ?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When the service `chill.main.timeline_builder` is instanciated, the service is informed of each service taggued with `chill.timeline` tags. Then,
When the service `chill.main.timeline_builder` is instanciated, the service is informed of each service taggued with `chill.timeline` tags. Then,
1. The service build an UNION query by assembling column and tables names provided by the `fetchQuery` result ;
2. The UNION query is run, the result contains an id and a type for each row (see :ref:`above <understanding-queries>`)
@@ -84,7 +86,7 @@ To push events on a timeline :
Implementing the TimelineProviderInterface
------------------------------------------
The has the following signature :
The has the following signature :
.. code-block:: php
@@ -92,19 +94,19 @@ The has the following signature :
interface TimelineProviderInterface
{
/**
*
/**
*
* @param string $context
* @param mixed[] $args the argument to the context.
* @return TimelineSingleQuery
* @throw \LogicException if the context is not supported
*/
public function fetchQuery($context, array $args);
/**
* Indicate if the result type may be handled by the service
*
*
* @param string $type the key present in the SELECT query
* @return boolean
*/
@@ -113,42 +115,42 @@ The has the following signature :
/**
* fetch entities from db into an associative array. The keys **MUST BE**
* the id
*
* All ids returned by all SELECT queries
*
* All ids returned by all SELECT queries
* (@see TimeLineProviderInterface::fetchQuery) and with the type
* supported by the provider (@see TimelineProviderInterface::supportsType)
* will be passed as argument.
*
*
* @param array $ids an array of id
* @return mixed[] an associative array of entities, with id as key
*/
public function getEntities(array $ids);
/**
* return an associative array with argument to render the entity
* in an html template, which will be included in the timeline page
*
*
* The result must have the following key :
*
*
* - `template` : the template FQDN
* - `template_data`: the data required by the template
*
*
*
*
* Example:
*
*
* ```
* array(
* array(
* 'template' => 'ChillMyBundle:timeline:template.html.twig',
* 'template_data' => array(
* 'accompanyingPeriod' => $entity,
* 'person' => $args['person']
* 'accompanyingPeriod' => $entity,
* 'person' => $args['person']
* )
* );
* ```
*
*
* `$context` and `$args` are defined by the bundle which will call the timeline
* rendering.
*
* rendering.
*
* @param type $entity
* @param type $context
* @param array $args
@@ -156,7 +158,7 @@ The has the following signature :
* @throws \LogicException if the context is not supported
*/
public function getEntityTemplate($entity, $context, array $args);
}
@@ -176,7 +178,7 @@ The parameters should be replaced into the query by :code:`?`. They will be repl
`$context` and `$args` are defined by the bundle which will call the timeline rendering. You may use them to build a different query depending on this context.
For instance, if the context is `'person'`, the args will be this array :
For instance, if the context is `'person'`, the args will be this array :
.. code-block:: php
@@ -197,7 +199,7 @@ You should find in the bundle documentation which contexts are arguments the bun
.. note::
We encourage to use `ClassMetaData` to define column names arguments. If you change your column names, changes will be reflected automatically during the execution of your code.
We encourage to use `ClassMetaData` to define column names arguments. If you change your column names, changes will be reflected automatically during the execution of your code.
Example of an implementation :
@@ -215,13 +217,13 @@ Example of an implementation :
*/
class TimelineReportProvider implements TimelineProviderInterface
{
/**
*
* @var EntityManager
*/
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
@@ -230,9 +232,9 @@ Example of an implementation :
public function fetchQuery($context, array $args)
{
$this->checkContext($context);
$metadata = $this->em->getClassMetadata('ChillReportBundle:Report');
return TimelineSingleQuery::fromArray([
'id' => $metadata->getColumnName('id'),
'type' => 'report',
@@ -254,11 +256,11 @@ Example of an implementation :
The `supportsType` function
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This function indicate to the master `chill.main.timeline_builder` service (which orchestrate the build of UNION queries) that the service supports the type indicated in the result's array of the `fetchQuery` function.
This function indicate to the master `chill.main.timeline_builder` service (which orchestrate the build of UNION queries) that the service supports the type indicated in the result's array of the `fetchQuery` function.
The implementation of our previous example will be :
The implementation of our previous example will be :
.. code-block:: php
.. code-block:: php
namespace Chill\ReportBundle\Timeline;
@@ -272,7 +274,7 @@ The implementation of our previous example will be :
//...
/**
*
*
* {@inheritDoc}
*/
public function supportsType($type)
@@ -304,12 +306,12 @@ The results **must be** an array where the id given by the UNION query (remember
{
$reports = $this->em->getRepository('ChillReportBundle:Report')
->findBy(array('id' => $ids));
$result = array();
foreach($reports as $report) {
$result[$report->getId()] = $report;
}
return $result;
}
@@ -318,9 +320,9 @@ The results **must be** an array where the id given by the UNION query (remember
The `getEntityTemplate` function
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is where the master service will collect information to render the entity.
This is where the master service will collect information to render the entity.
The result must be an associative array with :
The result must be an associative array with :
- **template** is the FQDN of the template ;
- **template_data** is an associative array where keys are the variables'names for this template, and values are the values.
@@ -332,8 +334,8 @@ Example :
array(
'template' => 'ChillMyBundle:timeline:template.html.twig',
'template_data' => array(
'period' => $entity,
'person' => $args['person']
'period' => $entity,
'person' => $args['person']
)
);
@@ -349,7 +351,7 @@ Create a timeline with his own context
You have to create a Controller which will execute the service `chill.main.timeline_builder`. Using the `Chill\MainBundle\Timeline\TimelineBuilder::getTimelineHTML` function, you will get an HTML representation of the timeline, which you may include with twig `raw` filter.
Example :
Example :
.. code-block:: php

View File

@@ -151,6 +151,7 @@ This script will :
# mount into to container
./docker-php.sh
bin/console chill:db:sync-views
# and load fixtures
bin/console doctrine:migrations:migrate
@@ -161,7 +162,7 @@ Chill will be available at ``http://localhost:8001.`` Currently, there isn't any
# mount into to container
./docker-php.sh
# and load fixtures
# and load fixtures (do not this for production)
bin/console doctrine:fixtures:load --purge-with-truncate
There are several users available:
@@ -204,8 +205,10 @@ How to create the database schema (= run migrations) ?
# if a container is running
./docker-php.sh
bin/console doctrine:migrations:migrate
bin/console chill:db:sync-views
# if not
docker-compose run --user $(id -u) php bin/console doctrine:migrations:migrate
docker-compose run --user $(id -u) php bin/console chill:db:sync-views
How to read the email sent by the program ?
@@ -236,6 +239,23 @@ How to open a terminal in the project
# if not
docker-compose run --user $(id -u) php /bin/bash
How to run cron-jobs ?
======================
Some command must be executed in :ref:`cron jobs <cronjob>`. To execute them:
.. code-block:: bash
# if a container is running
./docker-php.sh
bin/console chill:cron-job:execute
# some of them are executed only during the night. So, we have to force the execution during the day:
bin/console chill:cron-job:execute 'name-of-the-cron'
# if not
docker-compose run --user $(id -u) php bin/console chill:cron-job:execute
# some of them are executed only during the night. So, we have to force the execution during the day:
docker-compose run --user $(id -u) php bin/console chill:cron-job:execute 'name-of-the-cron'
How to run composer ?
=====================

View File

@@ -38,6 +38,14 @@ This should be adapted to your needs:
* Think about how you will backup your database. Some adminsys find easier to store database outside of docker, which might be easier to administrate or replicate.
Run migrations on each update
=============================
Every time you start a new version, you should apply update the sql schema:
- running ``bin/console doctrine:migration:migrate`` to run sql migration;
- synchonizing sql views to the last state: ``bin/console chill:db:sync-views``
Cron jobs
=========