Merge branch 'features/household-members-list' into 'master'

Features/household members list

See merge request Chill-Projet/chill-bundles!76
This commit is contained in:
Julien Fastré 2021-06-10 08:59:51 +00:00
commit f7bb9ac327
22 changed files with 559 additions and 53 deletions

View File

@ -58,7 +58,8 @@
"symfony/css-selector": "^5.2",
"twig/markdown-extra": "^3.3",
"erusev/parsedown": "^1.7",
"symfony/serializer": "^5.2"
"symfony/serializer": "^5.2",
"symfony/webpack-encore-bundle": "^1.11"
},
"conflict": {
"symfony/symfony": "*"

View File

@ -18,7 +18,7 @@
// @import "bootstrap/scss/tables";
// @import "bootstrap/scss/forms";
// @import "bootstrap/scss/buttons";
// @import "bootstrap/scss/transitions";
@import "bootstrap/scss/transitions";
// @import "bootstrap/scss/dropdown";
// @import "bootstrap/scss/button-group";
// @import "bootstrap/scss/input-group";

View File

@ -4,6 +4,8 @@
// Or compile bootstrap only enabled assets
require('./bootstrap.scss');
// You can specify which plugins you need
//import { Tooltip, Toast, Popover } from 'bootstrap';
import Modal from 'bootstrap/js/dist/modal';
import Collapse from 'bootstrap/js/src/collapse';

View File

@ -41,12 +41,6 @@ table {
}
}
// règle la typo des étiquettes de dénomination rendues avec renderBox
.chill_denomination {
font-size: 1.3em;
font-weight: 700;
}
/*
* ACCOMPANYING_COURSE
* Header custom for Accompanying Course

View File

@ -28,16 +28,16 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{{ installation.name }} - {% block title %}{% endblock %}</title>
<link rel="shortcut icon" href="{{ asset('build/images/favicon.ico') }}" type="image/x-icon">
<link rel="stylesheet" href="{{ asset('build/scratch.css') }}"/>
<link rel="stylesheet" href="{{ asset('build/chill.css') }}"/>
{{ encore_entry_link_tags('scratch') }}
{{ encore_entry_link_tags('chill') }}
{% if active_bootstrap == 1 %}
<link rel="stylesheet" href="{{ asset('build/bootstrap.css') }}" type="text/css"/>
{{ encore_entry_link_tags('bootstrap') }}
{% endif %}
{% if active_forkawesome == 1 %}
<link rel="stylesheet" href="{{ asset('build/forkawesome.css') }}" type="text/css"/>
{{ encore_entry_link_tags('forkawesome') }}
{% endif %}
{% if active_ckeditor == 1 %}
<link rel="stylesheet" href="{{ asset('build/ckeditor5.css') }}" type="text/css"/>
{{ encore_entry_link_tags('ckeditor5') }}
{% endif %}
{% block css%}<!-- nothing added to css -->{% endblock %}
</head>
@ -152,17 +152,16 @@
{{ include('@ChillMain/Layout/_footer.html.twig') }}
<script type="text/javascript" src="{{ asset('build/runtime.js') }}"></script>
<script type="text/javascript" src="{{ asset('build/scratch.js') }}"></script>
<script type="text/javascript" src="{{ asset('build/chill.js') }}"></script>
{{ encore_entry_script_tags('scratch') }}
{{ encore_entry_script_tags('chill') }}
{% if active_bootstrap == 1 %}
<script type="text/javascript" src="{{ asset('build/bootstrap.js') }}"></script>
{{ encore_entry_script_tags('bootstrap') }}
{% endif %}
{% if active_forkawesome == 1 %}
<script type="text/javascript" src="{{ asset('build/forkawesome.js') }}"></script>
{{ encore_entry_script_tags('forkawesome') }}
{% endif %}
{% if active_ckeditor == 1 %}
<script type="text/javascript" src="{{ asset('build/ckeditor5.js') }}"></script>
{{ encore_entry_script_tags('ckeditor5') }}
{% endif %}
<script type="text/javascript">
chill.checkOtherValueOnChange();

View File

@ -8,6 +8,7 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Household\Position;
/**
* @Route("/{_locale}/person/household")
@ -25,9 +26,20 @@ class HouseholdController extends AbstractController
public function summary(Request $request, Household $household)
{
// TODO ACL
$positions = $this->getDoctrine()->getManager()
->getRepository(Position::class)
->findAll()
;
// little performance improvement:
// initialize members collection, which will avoid
// some queries
$household->getMembers()->initialize();
return $this->render('@ChillPerson/Household/summary.html.twig',
[
'household' => $household
'household' => $household,
'positions' => $positions
]
);
}
@ -43,9 +55,20 @@ class HouseholdController extends AbstractController
public function members(Request $request, Household $household)
{
// TODO ACL
$positions = $this->getDoctrine()->getManager()
->getRepository(Position::class)
->findAll()
;
// little performance improvement:
// initialize members collection, which will avoid
// some queries
$household->getMembers()->initialize();
return $this->render('@ChillPerson/Household/members.html.twig',
[
'household' => $household
'household' => $household,
'positions' => $positions
]
);
}

View File

@ -2,17 +2,32 @@
namespace Chill\PersonBundle\Controller;
use Chill\PersonBundle\Form\HouseholdMemberType;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
use Symfony\Component\HttpFoundation\Exception\BadRequestException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Serializer\Exception;
use Symfony\Component\Routing\Annotation\Route;
use Chill\MainBundle\CRUD\Controller\ApiController;
use Symfony\Component\Translation\TranslatorInterface;
use Chill\PersonBundle\Household\MembersEditor;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
class HouseholdMemberController extends ApiController
{
private UrlGeneratorInterface $generator;
private TranslatorInterface $translator;
public function __construct(UrlGeneratorInterface $generator, TranslatorInterface $translator)
{
$this->generator = $generator;
$this->translator = $translator;
}
/**
* @Route(
* "/api/1.0/person/household/members/move.{_format}",
@ -44,4 +59,39 @@ class HouseholdMemberController extends ApiController
"groups" => ["read"],
]);
}
/**
* @Route(
* "/{_locale}/person/household/member/{id}/edit",
* name="chill_person_household_member_edit"
* )
*/
public function editMembership(Request $request, HouseholdMember $member): Response
{
// TODO ACL
$form = $this->createForm(HouseholdMemberType::class, $member);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->getDoctrine()->getManager()->flush();
$this->addFlash('success', $this->translator
->trans('household.successfully saved member'))
;
return $this->redirect(
$request->get('returnPath', null) ??
$this->generator->generate('chill_person_household_members', [ 'household_id' =>
$member->getHousehold()->getId() ])
);
}
return $this->render('@ChillPerson/Household/Member/edit.html.twig', [
'household' => $member->getHousehold(),
'member' => $member,
'form' => $form->createView()
]);
}
}

View File

@ -5,6 +5,7 @@ namespace Chill\PersonBundle\Entity\Household;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;
use Symfony\Component\Serializer\Annotation as Serializer;
use Chill\MainBundle\Entity\Address;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
@ -97,6 +98,79 @@ class Household
return $this->members;
}
public function getCurrentMembers(?\DateTimeImmutable $now = null): Collection
{
$criteria = new Criteria();
$expr = Criteria::expr();
$date = $now === null ? (new \DateTimeImmutable('now')) : $now;
$criteria
->where($expr->orX(
$expr->isNull('startDate'),
$expr->lte('startDate', $date)
))
->andWhere($expr->orX(
$expr->isNull('endDate'),
$expr->gte('endDate', $date)
));
return $this->getMembers()->matching($criteria);
}
/**
* Get the persons currently associated to the household.
*
* Return a list of Person, instead of a list of HouseholdMembers
*
* @return Person[]
*/
public function getCurrentPersons(?\DateTimeImmutable $now = null): Collection
{
return $this->getCurrentMembers($now)
->map(function(HouseholdMember $m) { return $m->getPerson(); });
}
public function getNonCurrentMembers(\DateTimeImmutable $now = null): Collection
{
$criteria = new Criteria();
$expr = Criteria::expr();
$date = $now === null ? (new \DateTimeImmutable('now')) : $now;
$criteria
->where(
$expr->gt('startDate', $date)
)
->orWhere(
$expr->andX(
$expr->lt('endDate', $date),
$expr->neq('endDate', null)
)
);
return $this->getMembers()->matching($criteria);
}
public function getCurrentMembersByPosition(Position $position, \DateTimeInterface $now = null)
{
$criteria = new Criteria();
$expr = Criteria::expr();
$criteria->where($expr->eq('position', $position));
return $this->getCurrentMembers($now)->matching($criteria);
}
public function getNonCurrentMembersByPosition(Position $position, \DateTimeInterface $now = null)
{
$criteria = new Criteria();
$expr = Criteria::expr();
$criteria->where($expr->eq('position', $position));
return $this->getNonCurrentMembers($now)->matching($criteria);
}
public function addMember(HouseholdMember $member): self
{
if (!$this->members->contains($member)) {

View File

@ -120,7 +120,7 @@ class HouseholdMember
return $this->endDate;
}
public function setEndDate(\DateTimeImmutable $endDate): self
public function setEndDate(?\DateTimeImmutable $endDate = null): self
{
$this->endDate = $endDate;

View File

@ -21,34 +21,34 @@ class Position
* @ORM\Column(type="integer")
* @Serializer\Groups({ "read" })
*/
private $id;
private ?int $id;
/**
* @ORM\Column(type="json")
*/
private $label = [];
private array $label = [];
/**
* @ORM\Column(type="boolean")
*/
private $shareHouseHold;
private bool $shareHouseHold = true;
/**
* @ORM\Column(type="boolean")
*/
private $allowHolder;
private bool $allowHolder = false;
/**
* @ORM\Column(type="float")
*/
private $ordering;
private float $ordering = 0.00;
public function getId(): ?int
{
return $this->id;
}
public function getLabel(): ?array
public function getLabel(): array
{
return $this->label;
}
@ -60,7 +60,7 @@ class Position
return $this;
}
public function getShareHousehold(): ?bool
public function getShareHousehold(): bool
{
return $this->shareHouseHold;
}
@ -72,11 +72,16 @@ class Position
return $this;
}
public function getAllowHolder(): ?bool
public function getAllowHolder(): bool
{
return $this->allowHolder;
}
public function isAllowHolder(): bool
{
return $this->getAllowHolder();
}
public function setAllowHolder(bool $allowHolder): self
{
$this->allowHolder = $allowHolder;
@ -84,7 +89,7 @@ class Position
return $this;
}
public function getOrdering(): ?float
public function getOrdering(): float
{
return $this->ordering;
}

View File

@ -0,0 +1,42 @@
<?php
namespace Chill\PersonBundle\Form;
use Chill\MainBundle\Form\Type\ChillTextareaType;
use Chill\MainBundle\Form\Type\ChillDateType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface;
class HouseholdMemberType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('startDate', ChillDateType::class, [
'label' => 'household.Start date',
'input' => 'datetime_immutable',
])
->add('endDate', ChillDateType::class, [
'label' => 'household.End date',
'input' => 'datetime_immutable',
'required' => false
])
;
if ($options['data']->getPosition()->isAllowHolder()) {
$builder
->add('holder', ChoiceType::class, [
'label' => 'household.holder',
'choices' => [
'household.is holder' => true,
'household.is not holder' => false
]
]);
}
$builder
->add('comment', ChillTextareaType::class, [
'label' => 'household.Comment'
])
;
}
}

View File

@ -29,21 +29,21 @@ class HouseholdMenuBuilder implements LocalMenuBuilderInterface
{
$household = $parameters['household'];
$menu->addChild($this->translator->trans('Summary'), [
$menu->addChild($this->translator->trans('household.Household summary'), [
'route' => 'chill_person_household_summary',
'routeParameters' => [
'household_id' => $household->getId()
]])
->setExtras(['order' => 10]);
$menu->addChild($this->translator->trans('Members'), [
$menu->addChild($this->translator->trans('household.Household members'), [
'route' => 'chill_person_household_members',
'routeParameters' => [
'household_id' => $household->getId()
]])
->setExtras(['order' => 20]);
$menu->addChild($this->translator->trans('Addresses'), [
$menu->addChild($this->translator->trans('household.Addresses'), [
'route' => 'chill_person_household_addresses',
'routeParameters' => [
'household_id' => $household->getId()

View File

@ -1,5 +1,21 @@
/// complete and overwrite flex-table in chillmain.scss
div.list-with-period {
div.list-with-period,
div.list-household-members,
div.list-household-members--summary {
.chill-entity__person {
.chill-entity__person__first-name,
.chill-entity__person__last-name {
font-size: 1.3em;
font-weight: 700;
}
}
.chill_denomination {
font-size: 1.3em;
font-weight: 700;
}
div.person {
ul.record_actions {
li {
@ -7,6 +23,9 @@ div.list-with-period {
}
}
}
div.comment {
// for the comment for household-members
}
div.periods {
div.header,
div.list-content {
@ -40,3 +59,5 @@ div.list-with-period {
}
}
}

View File

@ -7,9 +7,11 @@
{%- for n in person.altNames -%}
{%- if loop.first -%}({% else %} {%- endif -%}
<span class="chill-entity__person__alt-name chill-entity__person__altname--{{ n.key }}">
{{ n.label }}
{{- n.label -}}
</span>
{%- if loop.last %}) {% endif -%}
{%- if loop.last -%}) {%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- if showLink is defined -%}</a>{%- endif -%}</span>
{%- if showLink is defined -%}</a>{%- endif -%}
{#- tricks to remove easily whitespace after template -#}
{%- if true -%}</span>{%- endif -%}

View File

@ -0,0 +1,28 @@
{% extends '@ChillPerson/Household/layout.html.twig' %}
{% block title 'household.Edit member household'|trans %}
{% block content %}
<h1>{{ block('title') }}</h1>
{{ form_start(form) }}
{{ form_widget(form) }}
<ul class="record_actions sticky-form-buttons">
<li class="cancel">
<a
href="{{ chill_return_path_or('chill_person_household_members', { 'household_id': household.id}) }}"
class="sc-button bt-cancel"
>
{{ 'Cancel'|trans }}
</a>
</li>
<li>
<button type="submit" class="sc-button bt-save">{{ 'Save'|trans }}</button>
</li>
</ul>
{{ form_end(form) }}
{% endblock %}

View File

@ -1,11 +1,11 @@
<div class="subheader">
<div class="subheader banner-household">
<div class="grid-12 parent" id="header-accompanying_course-name" >
<div class="grid-10 push-1 grid-mobile-12 grid-tablet-12 push-mobile-0 push-tablet-0 parent">
<div class="grid-6">{% set title = title %}
<h1>
<i class="fa fa-child"></i>
{{ 'Household'|trans }}
<i class="fa fa-home"></i>
{{ 'household.Household'|trans }}
<span style="font-weight: lighter; font-size: 50%;">(n°{{ household.id }})</span>
</h1>
</div>
@ -18,9 +18,23 @@
</div>
<div class="grid-12 parent" id="header-accompanying_course-details" >
<div class="grid-10 push-1 grid-mobile-12 grid-tablet-12 push-mobile-0 push-tablet-0 parent">
<div id="banner-misc"></div>
<div id="banner-misc">
{%- set persons = household.getCurrentPersons() -%}
{%- if persons|length > 0 -%}
<span class="current-members-explain">
{{- 'household.Current household members'|trans }}:
</span>
{%- for p in persons|slice(0, 5) -%}
{{- p|chill_entity_render_box({'addLink': false}) -}}
{%- if false == loop.last -%}, {% endif -%}
{%- endfor -%}
{% if persons|length > 5 %}
<span class="current-members-more">
{{ 'household.and x other persons'|trans({'x': persons|length-5}) }}
</span>
{% endif %}
{%- endif -%}
</div>
</div>
</div>
</div>

View File

@ -1,10 +1,138 @@
{% extends '@ChillPerson/Household/layout.html.twig' %}
{% block title 'Household members'|trans %}
{% block title 'household.Household members'|trans %}
{% block content %}
<h1>{{ block('title') }}</h1>
<p>Household with id {{ household.id }}</p>
{% for p in positions %}
<h3>{{ p.label|localize_translatable_string }}</h3>
{% if false == p.shareHousehold %}
<p>{{ 'household.Those members does not share address'|trans }}</p>
{% endif %}
{%- set members = household.currentMembersByPosition(p) %}
{% if members|length > 0 %}
<div class="flex-table list-household-members">
{% for m in members %}
<div class="item-bloc">
<div class="item-row person">
<div class="item-col box-person">
<div>
{{ m.person|chill_entity_render_box({'addLink': true}) }}
{% if m.holder %}
<span class="badge badge-primary">{{ 'household.holder'|trans }}</span>
{% endif %}
</div>
<div>
{{ 'Born the date'|trans({ 'gender': m.person.gender, 'birthdate': m.person.birthdate|format_date('long') }) }}
</div>
</div>
<div class="item-col box-where">
<ul class="list-content fa-ul">
{% if m.startDate is not empty %}
<li>{{ 'Since %date%'|trans({'%date%': m.startDate|format_date('long') }) }}</li>
{% endif %}
{% if m.endDate is not empty %}
<li>{{ 'Until %date%'|trans({'%date%': m.endDate|format_date('long') }) }}</li>
{% endif %}
</ul>
<ul class="record_actions">
<li>
<a
href="{{ chill_path_add_return_path('chill_person_household_member_edit', { 'id': m.id }) }}"
class="sc-button bt-edit"
/>
{{ 'household.Update membership'|trans }}
</a>
</li>
<li>
<a href="#" class="sc-button" /><i class="fa fa-sign-out"></i>{{ 'household.Leave'|trans }}</a>
</li>
</ul>
</div>
</div>
{% if m.comment is not empty %}
<div class="item-row comment">
<blockquote class="chill-user-quote">
{{ m.comment|chill_markdown_to_html }}
</blockquote>
</div>
{% endif %}
</div>
{% endfor %}
</div>
{% else %}
<p class="chill-no-data-statement">{{ 'household.Any persons into this position'|trans }}</p>
{% endif %}
{% set members = household.nonCurrentMembersByPosition(p) %}
{% if members|length > 0 %}
<p><!-- force a space after table --></p>
<button class="sc-button bt-green" type="button" data-toggle="collapse" data-target="#nonCurrent_{{ p.id }}" aria-expanded="false" aria-controls="collapse non current members">
{{ 'household.Show future or past memberships'|trans({'length': members|length}) }}
</button>
<div id="nonCurrent_{{ p.id }}" class="collapse">
<div class="flex-table list-household-members">
{% for m in members %}
<div class="item-bloc">
<div class="item-row person">
<div class="item-col box-person">
<div>
{{ m.person|chill_entity_render_box({'addLink': true}) }}
{% if m.holder %}
<span class="badge badge-primary">{{ 'household.holder'|trans }}</span>
{% endif %}
</div>
<div>
{{ 'Born the date'|trans({ 'gender': m.person.gender, 'birthdate': m.person.birthdate|format_date('long') }) }}
</div>
</div>
<div class="item-col box-where">
<ul class="list-content fa-ul">
{% if m.startDate is not empty %}
<li>{{ 'Since %date%'|trans({'%date%': m.startDate|format_date('long') }) }}</li>
{% endif %}
{% if m.endDate is not empty %}
<li>{{ 'Until %date%'|trans({'%date%': m.endDate|format_date('long') }) }}</li>
{% endif %}
</ul>
<ul class="record_actions">
<li>
<a
href="{{ chill_path_add_return_path('chill_person_household_member_edit', { 'id': m.id }) }}"
class="sc-button bt-edit"
/>
{{ 'household.Update membership'|trans }}
</a>
</li>
</ul>
</div>
</div>
{% if m.comment is not empty %}
<div class="item-row comment">
<blockquote class="chill-user-quote">
{{ m.comment|chill_markdown_to_html }}
</blockquote>
</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
<ul class="record_actions sticky-form-buttons">
<li>
<a class="sc-button bt-create">
{{ 'household.Add a member'|trans }}
</a>
</li>
</ul>
{% endblock %}

View File

@ -1,14 +1,53 @@
{% extends '@ChillPerson/Household/layout.html.twig' %}
{% block title 'Household summary'|trans %}
{% block title 'household.Household summary'|trans %}
{% block content %}
<h1>{{ block('title') }}</h1>
<p>Household with id {{ household.id }}</p>
<h2>{{ 'household.Current household members'|trans }}</h2>
<h2>{{ 'Actual household members'|trans }}</h2>
{% for p in positions %}
{%- set members = household.currentMembersByPosition(p) %}
{% if members|length > 0 %}
<h3>{{ p.label|localize_translatable_string }}</h3>
<p>TODO</p>
{% if false == p.shareHousehold %}
<p>{{ 'household.Those members does not share address'|trans }}</p>
{% endif %}
<div class="flex-table list-household-members--summary">
{% for m in members %}
<div class="item-bloc">
<div class="item-row person">
<div class="item-col box-person">
<div>
{{ m.person|chill_entity_render_box({'addLink': true}) }}
{% if m.holder %}
<span class="badge badge-primary">{{ 'household.holder'|trans }}</span>
{% endif %}
</div>
<div>
{{ 'Born the date'|trans({ 'gender': m.person.gender, 'birthdate': m.person.birthdate|format_date('long') }) }}
</div>
</div>
<div class="item-col box-where">
<ul class="list-content fa-ul">
{% if m.startDate is not empty %}
<li>{{ 'Since %date%'|trans({'%date%': m.startDate|format_date('long') }) }}</li>
{% endif %}
{% if m.endDate is not empty %}
<li>{{ 'Until %date%'|trans({'%date%': m.endDate|format_date('long') }) }}</li>
{% endif %}
</ul>
</div>
</div>
</div>
{% endfor %}
</div>
{% endif %}
{% endfor %}
{% endblock %}

View File

@ -8,6 +8,7 @@ use Chill\MainBundle\Test\PrepareClientTrait;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Household\Household;
use Chill\PersonBundle\Entity\Household\HouseholdMember;
use Chill\PersonBundle\Entity\Household\Position;
use Doctrine\ORM\EntityManagerInterface;
@ -17,7 +18,7 @@ class HouseholdMemberControllerTest extends WebTestCase
use PrepareClientTrait;
/**
* @dataProvider provideValidData
* @dataProvider provideValidDataMove
*/
public function testMoveMember($personId, $householdId, $positionId, \DateTimeInterface $date)
{
@ -66,7 +67,31 @@ class HouseholdMemberControllerTest extends WebTestCase
);
}
public function provideValidData(): \Iterator
/**
* @dataProvider provideValidDataEditMember
*/
public function testEditMember($memberId)
{
$client = $this->getClientAuthenticated();
$crawler = $client->request(
Request::METHOD_GET,
"/fr/person/household/member/{$memberId}/edit"
);
$this->assertResponseIsSuccessful();
$form = $crawler->selectButton('Enregistrer')
->form();
$form['household_member[endDate]'] = (new \DateTime('tomorrow'))
->format('Y-m-d');
$crawler = $client->submit($form);
$this->assertEquals(302, $client->getResponse()->getStatusCode());
}
public function provideValidDataMove(): \Iterator
{
self::bootKernel();
$em = self::$container->get(EntityManagerInterface::class);
@ -95,4 +120,22 @@ class HouseholdMemberControllerTest extends WebTestCase
new \DateTimeImmutable('today')
];
}
public function provideValidDataEditMember(): \Iterator
{
self::bootKernel();
$em = self::$container->get(EntityManagerInterface::class);
$membershipIds = $em->createQuery("SELECT m.id FROM ".HouseholdMember::class." m ".
"JOIN m.person p ".
"JOIN p.center c ".
"WHERE c.name = :center AND m.endDate IS NULL")
->setParameter('center', 'Center A')
->getScalarResult()
;
\shuffle($membershipIds);
yield [ \array_pop($membershipIds)['id'] ];
}
}

View File

@ -63,6 +63,11 @@ services:
resource: '../Repository/'
tags: ['doctrine.repository_service']
Chill\PersonBundle\Controller\:
autowire: true
resource: '../Controller/'
tags: ['controller.service_arguments']
Chill\PersonBundle\Templating\Entity\:
autowire: true
autoconfigure: true

View File

@ -0,0 +1,37 @@
Born the date: >-
{gender, select,
man {Né le {birthdate}}
woman {Née le {birthdate}}
other {Né·e le {birthdate}}
}
household:
Household: Ménage
Household members: Membres du ménage
Show future or past memberships: >-
{length, plural,
one {Montrer une ancienne appartenance}
many {Montrer # anciennes ou futures appartenances}
other {Montrer # anciennes ou futures appartenances}
}
Those members does not share address: Ces usagers ne partagent pas l'adresse du ménage.
Any persons into this position: Aucune personne n'appartient au ménage à cette position.
Leave: Quitter le ménage
Update membership: Modifier
successfully saved member: Membre enregistré avec succès
Start date: Date de début de l'appartenance au ménage
End date: Date de fin de l'appartenance au ménage
Comment: Commentaire
is holder: Est titulaire
is not holder: N'est pas titulaire
holder: Titulaire
Edit member household: Modifier l'appartenance au ménage
Current household members: Membres actuels du ménage
Household summary: Résumé
Addresses: Adresses
and x other persons: >-
{x, plural,
one {et une autre personne}
many {et # autres personnes}
other {et # autres personnes}
}

View File

@ -46,7 +46,6 @@ Add new phone: Ajouter un numéro de téléphone
Remove phone: Supprimer
'Notes on contact information': 'Remarques sur les informations de contact'
'Remarks': 'Remarques'
'Born the %date%': '{0} Né le %date% | {1} Née le %date%'
'Spoken languages': 'Langues parlées'
'Unknown spoken languages': 'Langues parlées inconnues'
Male: Homme