Merge remote-tracking branch 'origin/master' into url_in_accompanyingPeriodWork_evaluations

This commit is contained in:
2022-03-06 22:33:16 +01:00
40 changed files with 543 additions and 145 deletions

View File

@@ -13,7 +13,7 @@ namespace Chill\PersonBundle\Controller;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\Person\ResidentialAddress;
use Chill\PersonBundle\Form\Type\ResidentialAddressType;
use Chill\PersonBundle\Form\ResidentialAddressType;
use Chill\PersonBundle\Repository\ResidentialAddressRepository;
use Chill\PersonBundle\Security\Authorization\PersonVoter;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

View File

@@ -18,8 +18,8 @@ use Chill\PersonBundle\Repository\ResidentialAddressRepository;
use Chill\ThirdPartyBundle\Entity\ThirdParty;
use DateTimeImmutable;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Serializer\Annotation\Context;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @ORM\Entity(repositoryClass=ResidentialAddressRepository::class)
@@ -49,7 +49,7 @@ class ResidentialAddress
* @ORM\ManyToOne(targetEntity=Person::class)
* @ORM\JoinColumn(nullable=true)
* @Groups({"read"})
* @Context(normalizationContext={"groups"={"minimal"}})
* @Context(normalizationContext={"groups": {"minimal"}})
*/
private ?Person $hostPerson = null;

View File

@@ -13,6 +13,7 @@ namespace Chill\PersonBundle\Entity;
use DateTime;
use Doctrine\ORM\Mapping as ORM;
use libphonenumber\PhoneNumber;
/**
* Person Phones.
@@ -51,9 +52,9 @@ class PersonPhone
private Person $person;
/**
* @ORM\Column(type="text", length=40, nullable=false)
* @ORM\Column(type="phone_number", nullable=false)
*/
private string $phonenumber = '';
private ?PhoneNumber $phonenumber = null;
/**
* @ORM\Column(type="text", length=40, nullable=true)
@@ -85,7 +86,7 @@ class PersonPhone
return $this->person;
}
public function getPhonenumber(): string
public function getPhonenumber(): ?PhoneNumber
{
return $this->phonenumber;
}
@@ -97,7 +98,8 @@ class PersonPhone
public function isEmpty(): bool
{
return empty($this->getDescription()) && empty($this->getPhonenumber());
return ("" === $this->getDescription() || null === $this->getDescription())
&& null === $this->getPhonenumber();
}
public function setDate(DateTime $date): void
@@ -115,7 +117,7 @@ class PersonPhone
$this->person = $person;
}
public function setPhonenumber(string $phonenumber): void
public function setPhonenumber(?PhoneNumber $phonenumber): void
{
$this->phonenumber = $phonenumber;
}

View File

@@ -27,6 +27,7 @@ use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\PersonPhone;
use Chill\PersonBundle\Form\Type\GenderType;
use Chill\PersonBundle\Form\Type\PersonAltNameType;
use Chill\PersonBundle\Form\Type\PersonPhoneType;
use Chill\PersonBundle\Form\Type\Select2MaritalStatusType;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\AbstractType;
@@ -158,7 +159,7 @@ class PersonType extends AbstractType
}
$builder->add('otherPhoneNumbers', ChillCollectionType::class, [
'entry_type' => ChillPhoneNumberType::class,
'entry_type' => PersonPhoneType::class,
'button_add_label' => 'Add new phone',
'button_remove_label' => 'Remove phone',
'required' => false,

View File

@@ -9,11 +9,12 @@
declare(strict_types=1);
namespace Chill\PersonBundle\Form\Type;
namespace Chill\PersonBundle\Form;
use Chill\MainBundle\Form\Type\CommentType;
use Chill\MainBundle\Form\Type\PickAddressType;
use Chill\PersonBundle\Entity\Person\ResidentialAddress;
use Chill\PersonBundle\Form\Type\PickPersonDynamicType;
use Chill\ThirdPartyBundle\Form\Type\PickThirdpartyDynamicType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;

View File

@@ -11,6 +11,7 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Form\Type;
use Chill\MainBundle\Form\Type\ChillPhoneNumberType;
use Chill\MainBundle\Phonenumber\PhonenumberHelper;
use Chill\PersonBundle\Entity\PersonPhone;
use Doctrine\ORM\EntityManagerInterface;
@@ -36,7 +37,7 @@ class PersonPhoneType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('phonenumber', TelType::class, [
$builder->add('phonenumber', ChillPhoneNumberType::class, [
'label' => 'Other phonenumber',
'required' => true,
]);

View File

@@ -32,26 +32,11 @@ class ResidentialAddressRepository extends ServiceEntityRepository
parent::__construct($registry, ResidentialAddress::class);
}
/**
* @param Person $person
* @param DateTimeImmutable|null $at
* @return array|ResidentialAddress[]|null
*/
public function findCurrentResidentialAddressByPerson(Person $person, ?DateTimeImmutable $at = null): array
{
return $this->buildQueryFindCurrentResidentialAddresses($person, $at)
->select('ra')
->getQuery()
->getResult();
}
public function buildQueryFindCurrentResidentialAddresses(Person $person, ?DateTimeImmutable $at = null): QueryBuilder
{
$date = null === $at ? new DateTimeImmutable('today') : $at;
$qb = $this->createQueryBuilder('ra');
$dateFilter = $qb->expr()->andX(
$qb->expr()->lte('ra.startDate', ':dateIn'),
$qb->expr()->orX(
@@ -69,6 +54,17 @@ class ResidentialAddressRepository extends ServiceEntityRepository
return $qb;
}
/**
* @return array|ResidentialAddress[]|null
*/
public function findCurrentResidentialAddressByPerson(Person $person, ?DateTimeImmutable $at = null): array
{
return $this->buildQueryFindCurrentResidentialAddresses($person, $at)
->select('ra')
->getQuery()
->getResult();
}
// /**
// * @return ResidentialAddress[] Returns an array of ResidentialAddress objects
// */

View File

@@ -170,7 +170,9 @@ export default {
console.log('data', payload.data)
body.name = payload.data.name;
body.email = payload.data.email;
body.telephone = payload.data.phonenumber;
body.telephone = payload.data.telephone;
body.civility = payload.data.civility;
body.profession = payload.data.profession;
body.address = payload.data.address ? { id: payload.data.address.address_id } : null;
makeFetch('PATCH', `/api/1.0/thirdparty/thirdparty/${payload.data.id}.json`, body)

View File

@@ -167,6 +167,18 @@
<span class="chill-no-data-statement">{{ 'No data given'|trans }}</span>
</li>
{% endif %}
{% if person.email is not null %}
<li>
<i class="fa fa-li fa-envelope-o"></i><a href="{{ 'mailto:' ~ person.email }}">
{{ person.email }}
</a>
</li>
{% else %}
<li>
<i class="fa fa-li fa-envelope-o"></i>
<span class="chill-no-data-statement">{{ 'No data given'|trans }}</span>
</li>
{% endif %}
{% if options['addCenter'] and person|chill_resolve_center|length > 0 %}
<li>
<i class="fa fa-li fa-long-arrow-right"></i>

View File

@@ -74,6 +74,7 @@ class PersonDocGenNormalizer implements
$data = [
'type' => 'person',
'id' => $person->getId(),
'isNull' => false,
'civility' => $this->normalizer->normalize($person->getCivility(), $format, array_merge($context, ['docgen:expects' => Civility::class])),
'firstName' => $person->getFirstName(),
@@ -151,7 +152,7 @@ class PersonDocGenNormalizer implements
$normalizer = new NormalizeNullValueHelper($this->normalizer, 'type', 'person');
$attributes = [
'firstName', 'lastName', 'age', 'altNames', 'text',
'id', 'firstName', 'lastName', 'age', 'altNames', 'text',
'civility' => Civility::class,
'birthdate' => DateTimeInterface::class,
'deathdate' => DateTimeInterface::class,

View File

@@ -31,6 +31,9 @@ use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
use Symfony\Component\Serializer\Normalizer\ObjectToPopulateTrait;
use function array_key_exists;
use function count;
use function in_array;
use function is_string;
/**
* Serialize a Person entity.
@@ -54,11 +57,11 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
private ResidentialAddressRepository $residentialAddressRepository;
public function __construct(
ChillEntityRenderExtension $render,
ChillEntityRenderExtension $render, /* TODO: replace by PersonRenderInterface, as sthis is the only one required */
PersonRepository $repository,
CenterResolverManagerInterface $centerResolverManager,
ResidentialAddressRepository $residentialAddressRepository,
PhoneNumberHelperInterface $phoneNumberHelper
PhoneNumberHelperInterface $phoneNumberHelper /* TODO maybe not necessayr any more */
) {
$this->render = $render;
$this->repository = $repository;
@@ -187,6 +190,10 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
public function normalize($person, $format = null, array $context = [])
{
$groups = $context[AbstractNormalizer::GROUPS] ?? [];
if (is_string($groups)) {
$groups = [$groups];
}
$household = $person->getCurrentHousehold();
$currentResidentialAddresses = $this->residentialAddressRepository->findCurrentResidentialAddressByPerson($person);
@@ -207,8 +214,8 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
'gender' => $person->getGender(),
];
if (in_array("minimal", $groups) && 1 === count($groups)) {
return $data;
if (in_array('minimal', $groups, true) && 1 === count($groups)) {
return $data;
}
return array_merge($data, [

View File

@@ -0,0 +1,179 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\PersonBundle\Service\DocGenerator;
use Chill\DocGeneratorBundle\Context\DocGeneratorContextWithAdminFormInterface;
use Chill\DocGeneratorBundle\Context\Exception\UnexpectedTypeException;
use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
use Chill\DocGeneratorBundle\Service\Context\BaseContextData;
use Chill\DocStoreBundle\Entity\PersonDocument;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\DocStoreBundle\Repository\DocumentCategoryRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\Person;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use function array_key_exists;
class PersonContext implements DocGeneratorContextWithAdminFormInterface
{
private BaseContextData $baseContextData;
private DocumentCategoryRepository $documentCategoryRepository;
private EntityManagerInterface $em;
private NormalizerInterface $normalizer;
private TranslatableStringHelperInterface $translatableStringHelper;
private TranslatorInterface $translator;
public function __construct(
DocumentCategoryRepository $documentCategoryRepository,
NormalizerInterface $normalizer,
TranslatableStringHelperInterface $translatableStringHelper,
EntityManagerInterface $em,
TranslatorInterface $translator,
BaseContextData $baseContextData
) {
$this->documentCategoryRepository = $documentCategoryRepository;
$this->normalizer = $normalizer;
$this->translatableStringHelper = $translatableStringHelper;
$this->em = $em;
$this->baseContextData = $baseContextData;
$this->translator = $translator;
}
public function adminFormReverseTransform(array $data): array
{
if (array_key_exists('category', $data)) {
$data['category'] = [
'idInsideBundle' => $data['category']->getIdInsideBundle(),
'bundleId' => $data['category']->getBundleId(),
];
}
return $data;
}
public function adminFormTransform(array $data): array
{
$r = [
'mainPerson' => $data['mainPerson'] ?? false,
'mainPersonLabel' => $data['mainPersonLabel'] ?? $this->translator->trans('docgen.Main person'),
];
if (array_key_exists('category', $data)) {
$r['category'] = array_key_exists('category', $data) ?
$this->documentCategoryRepository->find($data['category']) : null;
}
return $r;
}
public function buildAdminForm(FormBuilderInterface $builder): void
{
$builder
->add('category', EntityType::class, [
'placeholder' => 'Choose a document category',
'class' => 'ChillDocStoreBundle:DocumentCategory',
'query_builder' => static function (EntityRepository $er) {
return $er->createQueryBuilder('c')
->where('c.documentClass = :docClass')
->setParameter('docClass', PersonDocument::class);
},
'choice_label' => function ($entity = null) {
return $entity ? $this->translatableStringHelper->localize($entity->getName()) : '';
},
]);
}
public function getData(DocGeneratorTemplate $template, $entity, array $contextGenerationData = []): array
{
if (!$entity instanceof Person) {
throw new UnexpectedTypeException($entity, Person::class);
}
$data = [];
$data = array_merge($data, $this->baseContextData->getData());
$data['person'] = $this->normalizer->normalize($entity, 'docgen', [
'docgen:expects' => Person::class,
'groups' => ['docgen:read', 'docgen:person:with-household', 'docgen:person:with-relations'],
]);
return $data;
}
public function getDescription(): string
{
return 'docgen.A basic context for person';
}
public function getEntityClass(): string
{
return Person::class;
}
public function getFormData(DocGeneratorTemplate $template, $entity): array
{
return [
'person' => $entity,
];
}
public static function getKey(): string
{
return self::class;
}
public function getName(): string
{
return 'docgen.Person basic';
}
public function hasAdminForm(): bool
{
return true;
}
/**
* @param Person $entity
*/
public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void
{
$doc = new PersonDocument();
$doc->setTemplate($template)
->setTitle($this->translatableStringHelper->localize($template->getName()))
->setDate(new DateTime())
->setDescription($this->translatableStringHelper->localize($template->getName()))
->setPerson($entity)
->setObject($storedObject);
if (array_key_exists('category', $template->getOptions())) {
$doc
->setCategory(
$this->documentCategoryRepository->find(
$template->getOptions()['category']
)
);
}
$this->em->persist($doc);
}
}

View File

@@ -38,6 +38,7 @@ final class PersonDocGenNormalizerTest extends KernelTestCase
use ProphecyTrait;
private const BLANK = [
'id' => '',
'firstName' => '',
'lastName' => '',
'altNames' => '',

View File

@@ -11,7 +11,15 @@ declare(strict_types=1);
namespace Serializer\Normalizer;
use Chill\MainBundle\Phonenumber\PhoneNumberHelperInterface;
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Repository\PersonRepository;
use Chill\PersonBundle\Repository\ResidentialAddressRepository;
use Chill\PersonBundle\Serializer\Normalizer\PersonJsonNormalizer;
use Prophecy\Argument;
use Prophecy\PhpUnit\ProphecyTrait;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
@@ -22,12 +30,27 @@ use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
*/
final class PersonJsonNormalizerTest extends KernelTestCase
{
private NormalizerInterface $normalizer;
use ProphecyTrait;
private PersonJsonNormalizer $normalizer;
protected function setUp(): void
{
self::bootKernel();
$this->normalizer = self::$container->get(NormalizerInterface::class);
$residentialAddressRepository = $this->prophesize(ResidentialAddressRepository::class);
$residentialAddressRepository
->findCurrentResidentialAddressByPerson(Argument::type(Person::class), Argument::any())
->willReturn([]);
$this->normalizer = $this->buildPersonJsonNormalizer(
self::$container->get(ChillEntityRenderExtension::class),
self::$container->get(PersonRepository::class),
self::$container->get(CenterResolverManagerInterface::class),
$residentialAddressRepository->reveal(),
self::$container->get(PhoneNumberHelperInterface::class),
self::$container->get(NormalizerInterface::class)
);
}
public function testNormalization()
@@ -37,4 +60,24 @@ final class PersonJsonNormalizerTest extends KernelTestCase
$this->assertIsArray($result);
}
private function buildPersonJsonNormalizer(
ChillEntityRenderExtension $render,
PersonRepository $repository,
CenterResolverManagerInterface $centerResolverManager,
ResidentialAddressRepository $residentialAddressRepository,
PhoneNumberHelperInterface $phoneNumberHelper,
NormalizerInterface $normalizer
): PersonJsonNormalizer {
$personJsonNormalizer = new PersonJsonNormalizer(
$render,
$repository,
$centerResolverManager,
$residentialAddressRepository,
$phoneNumberHelper
);
$personJsonNormalizer->setNormalizer($normalizer);
return $personJsonNormalizer;
}
}

View File

@@ -541,6 +541,8 @@ docgen:
A basic context for accompanying period: Contexte pour les parcours
A context for accompanying period work: Contexte pour les actions d'accompagnement
A context for accompanying period work evaluation: Contexte pour les évaluations dans les actions d'accompagnement
Person basic: Personne (basique)
A basic context for person: Contexte pour les personnes
period_notification:
period_designated_subject: Vous êtes référent d'un parcours d'accompagnement