mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-20 22:53:49 +00:00
Merge remote-tracking branch 'origin/master' into issue385_comments_accourse
This commit is contained in:
@@ -9,19 +9,20 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\AccompanyingPeriod\Workflow;
|
||||
namespace Chill\PersonBundle\AccompanyingPeriod\Events;
|
||||
|
||||
use Chill\MainBundle\Entity\Notification;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\Persistence\Event\LifecycleEventArgs;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
use Symfony\Component\Workflow\Event\EnteredEvent;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class WorkflowEventSubscriber implements EventSubscriberInterface
|
||||
class UserRefEventSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
@@ -55,23 +56,46 @@ class WorkflowEventSubscriber implements EventSubscriberInterface
|
||||
}
|
||||
}
|
||||
|
||||
public function postUpdate(AccompanyingPeriod $period, LifecycleEventArgs $args): void
|
||||
{
|
||||
if ($period->hasPreviousUser()
|
||||
&& $period->getUser() !== $this->security->getUser()
|
||||
&& $period->getStep() !== AccompanyingPeriod::STEP_DRAFT
|
||||
) {
|
||||
$this->generateNotificationToUser($period);
|
||||
}
|
||||
|
||||
// we are just out of a flush operation. Launch a new one
|
||||
$this->em->flush();
|
||||
}
|
||||
|
||||
private function generateNotificationToUser(AccompanyingPeriod $period)
|
||||
{
|
||||
$notification = new Notification();
|
||||
|
||||
$urgentStatement =
|
||||
$period->isEmergency() ? strtoupper($this->translator->trans('accompanying_period.emergency')) . ' ' : '';
|
||||
|
||||
$notification
|
||||
->setRelatedEntityId($period->getId())
|
||||
->setRelatedEntityClass(AccompanyingPeriod::class)
|
||||
->setTitle($urgentStatement . $this->translator->trans('period_notification.period_designated_subject'))
|
||||
->setMessage($this->engine->render(
|
||||
'@ChillPerson/Notification/accompanying_course_designation.md.twig',
|
||||
[
|
||||
'accompanyingCourse' => $period,
|
||||
]
|
||||
))
|
||||
->addAddressee($period->getUser());
|
||||
|
||||
$this->em->persist($notification);
|
||||
}
|
||||
|
||||
private function onPeriodConfirmed(AccompanyingPeriod $period)
|
||||
{
|
||||
if ($period->getUser() instanceof User
|
||||
&& $period->getUser() !== $this->security->getUser()) {
|
||||
$notification = new Notification();
|
||||
$notification
|
||||
->setRelatedEntityId($period->getId())
|
||||
->setRelatedEntityClass(AccompanyingPeriod::class)
|
||||
->setTitle($this->translator->trans('period_notification.period_designated_subject'))
|
||||
->setMessage($this->engine->render(
|
||||
'@ChillPerson/Notification/accompanying_course_designation.md.twig',
|
||||
[
|
||||
'accompanyingCourse' => $period,
|
||||
]
|
||||
))
|
||||
->addAddressee($period->getUser());
|
||||
$this->em->persist($notification);
|
||||
$this->generateNotificationToUser($period);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,149 @@
|
||||
<?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\Controller;
|
||||
|
||||
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||
use Chill\PersonBundle\Entity\Household\Household;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdComposition;
|
||||
use Chill\PersonBundle\Form\HouseholdCompositionType;
|
||||
use Chill\PersonBundle\Repository\Household\HouseholdCompositionRepository;
|
||||
use Chill\PersonBundle\Security\Authorization\HouseholdVoter;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class HouseholdCompositionController
|
||||
{
|
||||
private EngineInterface $engine;
|
||||
|
||||
private EntityManagerInterface $entityManager;
|
||||
|
||||
private FormFactoryInterface $formFactory;
|
||||
|
||||
private HouseholdCompositionRepository $householdCompositionRepository;
|
||||
|
||||
private PaginatorFactory $paginatorFactory;
|
||||
|
||||
private Security $security;
|
||||
|
||||
private TranslatorInterface $translator;
|
||||
|
||||
private UrlGeneratorInterface $urlGenerator;
|
||||
|
||||
public function __construct(
|
||||
Security $security,
|
||||
HouseholdCompositionRepository $householdCompositionRepository,
|
||||
PaginatorFactory $paginatorFactory,
|
||||
FormFactoryInterface $formFactory,
|
||||
EntityManagerInterface $entityManager,
|
||||
TranslatorInterface $translator,
|
||||
EngineInterface $engine,
|
||||
UrlGeneratorInterface $urlGenerator
|
||||
) {
|
||||
$this->security = $security;
|
||||
$this->householdCompositionRepository = $householdCompositionRepository;
|
||||
$this->paginatorFactory = $paginatorFactory;
|
||||
$this->formFactory = $formFactory;
|
||||
$this->entityManager = $entityManager;
|
||||
$this->translator = $translator;
|
||||
$this->engine = $engine;
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{_locale}/person/household/{id}/composition/index", name="chill_person_household_composition_index")
|
||||
*/
|
||||
public function index(Household $household, Request $request): Response
|
||||
{
|
||||
if (!$this->security->isGranted(HouseholdVoter::SEE, $household)) {
|
||||
throw new AccessDeniedException('not allowed to edit an household');
|
||||
}
|
||||
|
||||
$count = $this->householdCompositionRepository->countByHousehold($household);
|
||||
$paginator = $this->paginatorFactory->create($count);
|
||||
$compositions = $this->householdCompositionRepository->findByHousehold(
|
||||
$household,
|
||||
['startDate' => 'DESC', 'id' => 'DESC'],
|
||||
$paginator->getItemsPerPage(),
|
||||
$paginator->getCurrentPageFirstItemNumber()
|
||||
);
|
||||
|
||||
if ($this->security->isGranted(HouseholdVoter::EDIT, $household)) {
|
||||
$isEdit = $request->query->has('edit');
|
||||
|
||||
if ($isEdit) {
|
||||
$householdCompositions = $household->getCompositions()->filter(static function (HouseholdComposition $composition) use ($request) {
|
||||
return $composition->getId() === $request->query->getInt('edit');
|
||||
});
|
||||
|
||||
if ($householdCompositions->count() !== 1) {
|
||||
throw new BadRequestHttpException('could not find the composition with this id associated to the household');
|
||||
}
|
||||
$householdComposition = $householdCompositions->first();
|
||||
} else {
|
||||
$householdComposition = (new HouseholdComposition())
|
||||
->setStartDate(new DateTimeImmutable());
|
||||
}
|
||||
$form = $this->formFactory->create(HouseholdCompositionType::class, $householdComposition);
|
||||
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
if (!$isEdit) {
|
||||
$this->entityManager->persist($householdComposition);
|
||||
$household->addComposition($householdComposition);
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
$request->getSession()->getFlashBag()->add(
|
||||
'success',
|
||||
$this->translator->trans('household_composition.Composition added')
|
||||
);
|
||||
|
||||
return new RedirectResponse(
|
||||
$this->urlGenerator->generate('chill_person_household_composition_index', [
|
||||
'id' => $household->getId(),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
if ($form->isSubmitted() && !$form->isValid()) {
|
||||
$request->getSession()->getFlashBag()->add(
|
||||
'warning',
|
||||
$this->translator->trans('This form contains errors')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return new Response($this->engine->render(
|
||||
'@ChillPerson/HouseholdComposition/index.html.twig',
|
||||
[
|
||||
'household' => $household,
|
||||
'compositions' => $compositions,
|
||||
'form' => isset($form) ? $form->createView() : null,
|
||||
'isPosted' => isset($form) ? $form->isSubmitted() : false,
|
||||
'editId' => $request->query->getInt('edit', -1),
|
||||
]
|
||||
));
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
<?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\Controller;
|
||||
|
||||
use Chill\MainBundle\CRUD\Controller\ApiController;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use UnexpectedValueException;
|
||||
|
||||
class HouseholdCompositionTypeApiController extends ApiController
|
||||
{
|
||||
/**
|
||||
* @param QueryBuilder $query
|
||||
*/
|
||||
protected function customizeQuery(string $action, Request $request, $query): void
|
||||
{
|
||||
switch ($action) {
|
||||
case '_index':
|
||||
$query->andWhere($query->expr()->eq('e.active', "'TRUE'"));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new UnexpectedValueException('unexepcted action: ' . $action);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
<?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\DataFixtures\ORM;
|
||||
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdCompositionType;
|
||||
use Doctrine\Bundle\FixturesBundle\FixtureGroupInterface;
|
||||
use Doctrine\Common\DataFixtures\AbstractFixture;
|
||||
use Doctrine\Persistence\ObjectManager;
|
||||
|
||||
class LoadHouseholdCompositionType extends AbstractFixture implements FixtureGroupInterface
|
||||
{
|
||||
public const TYPES = [
|
||||
['fr' => 'Couple avec enfant(s)'],
|
||||
['fr' => 'Couple sans enfant'],
|
||||
['fr' => 'Mère seule'],
|
||||
['fr' => 'Père seul'],
|
||||
['fr' => 'Mère isolée'],
|
||||
['fr' => 'Père isolé'],
|
||||
['fr' => 'Homme seul'],
|
||||
['fr' => 'Femme seule'],
|
||||
];
|
||||
|
||||
public static function getGroups(): array
|
||||
{
|
||||
return ['composition-type'];
|
||||
}
|
||||
|
||||
public function load(ObjectManager $manager)
|
||||
{
|
||||
foreach (self::TYPES as $type) {
|
||||
$manager->persist(
|
||||
(new HouseholdCompositionType())
|
||||
->setLabel($type)
|
||||
);
|
||||
}
|
||||
|
||||
$manager->flush();
|
||||
}
|
||||
}
|
@@ -13,6 +13,7 @@ namespace Chill\PersonBundle\DependencyInjection;
|
||||
|
||||
use Chill\MainBundle\DependencyInjection\MissingBundleException;
|
||||
use Chill\MainBundle\Security\Authorization\ChillExportVoter;
|
||||
use Chill\PersonBundle\Controller\HouseholdCompositionTypeApiController;
|
||||
use Chill\PersonBundle\Doctrine\DQL\AddressPart;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodResourceVoter;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||
@@ -760,6 +761,21 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'class' => \Chill\PersonBundle\Entity\Household\HouseholdCompositionType::class,
|
||||
'name' => 'household_composition',
|
||||
'base_path' => '/api/1.0/person/houehold/composition/type',
|
||||
'base_role' => 'ROLE_USER',
|
||||
'controller' => HouseholdCompositionTypeApiController::class,
|
||||
'actions' => [
|
||||
'_index' => [
|
||||
'methods' => [
|
||||
Request::METHOD_GET => true,
|
||||
Request::METHOD_HEAD => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
@@ -327,6 +327,13 @@ class AccompanyingPeriod implements
|
||||
*/
|
||||
private ?User $user = null;
|
||||
|
||||
/**
|
||||
* Temporary field, which is filled when the user is changed.
|
||||
*
|
||||
* Used internally for listener when user change
|
||||
*/
|
||||
private ?User $userPrevious = null;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity=AccompanyingPeriodWork::class,
|
||||
@@ -755,6 +762,11 @@ class AccompanyingPeriod implements
|
||||
return $this->pinnedComment;
|
||||
}
|
||||
|
||||
public function getPreviousUser(): ?User
|
||||
{
|
||||
return $this->userPrevious;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|SocialAction[] All the descendant social actions of all
|
||||
* the descendants of the entity
|
||||
@@ -868,6 +880,11 @@ class AccompanyingPeriod implements
|
||||
return $this->works;
|
||||
}
|
||||
|
||||
public function hasPreviousUser(): bool
|
||||
{
|
||||
return null !== $this->userPrevious;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the closing date is after the opening date.
|
||||
*/
|
||||
@@ -1175,6 +1192,10 @@ class AccompanyingPeriod implements
|
||||
|
||||
public function setUser(User $user): self
|
||||
{
|
||||
if ($this->user !== $user) {
|
||||
$this->userPrevious = $this->user;
|
||||
}
|
||||
|
||||
$this->user = $user;
|
||||
|
||||
return $this;
|
||||
|
@@ -11,6 +11,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Entity\Household;
|
||||
|
||||
use ArrayIterator;
|
||||
use Chill\MainBundle\Entity\Address;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use Chill\PersonBundle\Validator\Constraints\Household\MaxHolder;
|
||||
@@ -23,8 +24,8 @@ use Doctrine\Common\Collections\Criteria;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
|
||||
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||
use function count;
|
||||
|
||||
/**
|
||||
@@ -56,6 +57,18 @@ class Household
|
||||
*/
|
||||
private CommentEmbeddable $commentMembers;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity=HouseholdComposition::class,
|
||||
* mappedBy="household",
|
||||
* orphanRemoval=true,
|
||||
* cascade={"persist"}
|
||||
* )
|
||||
* @ORM\OrderBy({"startDate": "DESC"})
|
||||
* @Assert\Valid(traverse=true, groups={"household_composition"})
|
||||
*/
|
||||
private Collection $compositions;
|
||||
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
@@ -90,6 +103,7 @@ class Household
|
||||
$this->addresses = new ArrayCollection();
|
||||
$this->members = new ArrayCollection();
|
||||
$this->commentMembers = new CommentEmbeddable();
|
||||
$this->compositions = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,6 +122,18 @@ class Household
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addComposition(HouseholdComposition $composition): self
|
||||
{
|
||||
if (!$this->compositions->contains($composition)) {
|
||||
$composition->setHousehold($this);
|
||||
$this->compositions[] = $composition;
|
||||
}
|
||||
|
||||
$this->householdCompositionConsistency();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addMember(HouseholdMember $member): self
|
||||
{
|
||||
if (!$this->members->contains($member)) {
|
||||
@@ -136,6 +162,14 @@ class Household
|
||||
return $this->commentMembers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArrayCollection|Collection|HouseholdComposition[]
|
||||
*/
|
||||
public function getCompositions(): Collection
|
||||
{
|
||||
return $this->compositions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Serializer\Groups({"read", "docgen:read"})
|
||||
* @Serializer\SerializedName("current_address")
|
||||
@@ -157,6 +191,31 @@ class Household
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getCurrentComposition(?DateTimeImmutable $at = null): ?HouseholdComposition
|
||||
{
|
||||
$at ??= new DateTimeImmutable('today');
|
||||
$criteria = new Criteria();
|
||||
$expr = Criteria::expr();
|
||||
|
||||
$criteria->where(
|
||||
$expr->andX(
|
||||
$expr->orX(
|
||||
$expr->isNull('endDate'),
|
||||
$expr->gt('endDate', $at)
|
||||
),
|
||||
$expr->lte('startDate', $at)
|
||||
)
|
||||
);
|
||||
|
||||
$compositions = $this->compositions->matching($criteria);
|
||||
|
||||
if ($compositions->count() > 0) {
|
||||
return $compositions->first();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Serializer\Groups({"docgen:read"})
|
||||
*/
|
||||
@@ -369,11 +428,54 @@ class Household
|
||||
return $this->waitingForBirthDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function householdCompositionConsistency(): void
|
||||
{
|
||||
$compositionOrdered = $this->compositions->toArray();
|
||||
|
||||
usort(
|
||||
$compositionOrdered,
|
||||
static function (HouseholdComposition $a, HouseholdComposition $b) {
|
||||
return $a->getStartDate() <=> $b->getStartDate();
|
||||
}
|
||||
);
|
||||
|
||||
$iterator = new ArrayIterator($compositionOrdered);
|
||||
$iterator->rewind();
|
||||
|
||||
/** @var ?HouseholdComposition $previous */
|
||||
$previous = null;
|
||||
|
||||
do {
|
||||
/** @var ?HouseholdComposition $current */
|
||||
$current = $iterator->current();
|
||||
|
||||
if (null !== $previous) {
|
||||
if (null === $previous->getEndDate() || $previous->getEndDate() > $current->getStartDate()) {
|
||||
$previous->setEndDate($current->getStartDate());
|
||||
}
|
||||
}
|
||||
$previous = $current;
|
||||
$iterator->next();
|
||||
} while ($iterator->valid());
|
||||
}
|
||||
|
||||
public function removeAddress(Address $address)
|
||||
{
|
||||
$this->addresses->removeElement($address);
|
||||
}
|
||||
|
||||
public function removeComposition(HouseholdComposition $composition): self
|
||||
{
|
||||
if ($this->compositions->removeElement($composition)) {
|
||||
$composition->setHousehold(null);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeMember(HouseholdMember $member): self
|
||||
{
|
||||
if ($this->members->removeElement($member)) {
|
||||
|
@@ -0,0 +1,171 @@
|
||||
<?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\Entity\Household;
|
||||
|
||||
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
|
||||
use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait;
|
||||
use Chill\MainBundle\Entity\Embeddable\CommentEmbeddable;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(
|
||||
* name="chill_person_household_composition"
|
||||
* )
|
||||
* @Serializer\DiscriminatorMap(typeProperty="type", mapping={
|
||||
* "household_composition_type": HouseholdCompositionType::class
|
||||
* })
|
||||
*/
|
||||
class HouseholdComposition implements TrackCreationInterface, TrackUpdateInterface
|
||||
{
|
||||
use TrackCreationTrait;
|
||||
use TrackUpdateTrait;
|
||||
|
||||
/**
|
||||
* @ORM\Embedded(class=CommentEmbeddable::class, columnPrefix="comment_")
|
||||
*/
|
||||
private CommentEmbeddable $comment;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
|
||||
* @Assert\GreaterThanOrEqual(propertyPath="startDate", groups={"Default", "household_composition"})
|
||||
*/
|
||||
private ?DateTimeImmutable $endDate = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=Household::class, inversedBy="compositions")
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
*/
|
||||
private ?Household $household = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=HouseholdCompositionType::class)
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
*/
|
||||
private ?HouseholdCompositionType $householdCompositionType = null;
|
||||
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
* @Serializer\Groups({"read", "docgen:read"})
|
||||
*/
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer", nullable=true, options={"default": null})
|
||||
* @Assert\NotNull
|
||||
* @Assert\GreaterThanOrEqual(0, groups={"Default", "household_composition"})
|
||||
*/
|
||||
private ?int $numberOfChildren = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date_immutable", nullable=false)
|
||||
* @Assert\NotNull(groups={"Default", "household_composition"})
|
||||
*/
|
||||
private ?DateTimeImmutable $startDate = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->comment = new CommentEmbeddable();
|
||||
}
|
||||
|
||||
public function getComment(): CommentEmbeddable
|
||||
{
|
||||
return $this->comment;
|
||||
}
|
||||
|
||||
public function getEndDate(): ?DateTimeImmutable
|
||||
{
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
public function getHousehold(): ?Household
|
||||
{
|
||||
return $this->household;
|
||||
}
|
||||
|
||||
public function getHouseholdCompositionType(): ?HouseholdCompositionType
|
||||
{
|
||||
return $this->householdCompositionType;
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getNumberOfChildren(): ?int
|
||||
{
|
||||
return $this->numberOfChildren;
|
||||
}
|
||||
|
||||
public function getStartDate(): ?DateTimeImmutable
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
public function setComment(CommentEmbeddable $comment): HouseholdComposition
|
||||
{
|
||||
$this->comment = $comment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setEndDate(?DateTimeImmutable $endDate): HouseholdComposition
|
||||
{
|
||||
$this->endDate = $endDate;
|
||||
|
||||
if (null !== $this->household) {
|
||||
$this->household->householdCompositionConsistency();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHousehold(?Household $household): HouseholdComposition
|
||||
{
|
||||
$this->household = $household;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHouseholdCompositionType(?HouseholdCompositionType $householdCompositionType): HouseholdComposition
|
||||
{
|
||||
$this->householdCompositionType = $householdCompositionType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setNumberOfChildren(?int $numberOfChildren): HouseholdComposition
|
||||
{
|
||||
$this->numberOfChildren = $numberOfChildren;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setStartDate(?DateTimeImmutable $startDate): HouseholdComposition
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
|
||||
if (null !== $this->household) {
|
||||
$this->household->householdCompositionConsistency();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
<?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\Entity\Household;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @ORM\Entity
|
||||
* @ORM\Table(
|
||||
* name="chill_person_household_composition_type"
|
||||
* )
|
||||
* @Serializer\DiscriminatorMap(typeProperty="type", mapping={
|
||||
* "household_composition_type": HouseholdCompositionType::class
|
||||
* })
|
||||
*/
|
||||
class HouseholdCompositionType
|
||||
{
|
||||
/**
|
||||
* @ORM\Column(type="boolean")
|
||||
*/
|
||||
private bool $active = true;
|
||||
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue
|
||||
* @ORM\Column(type="integer")
|
||||
* @Serializer\Groups({"read", "docgen:read"})
|
||||
*/
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="json")
|
||||
* @Serializer\Groups({"read", "docgen:read"})
|
||||
* @Serializer\Context({"is-translatable": true}, groups={"docgen:read"})
|
||||
*/
|
||||
private array $label = [];
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getLabel(): array
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
public function isActive(): bool
|
||||
{
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
public function setActive(bool $active): HouseholdCompositionType
|
||||
{
|
||||
$this->active = $active;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setLabel(array $label): HouseholdCompositionType
|
||||
{
|
||||
$this->label = $label;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
@@ -1142,7 +1142,7 @@ class Person implements HasCenterInterface, TrackCreationInterface, TrackUpdateI
|
||||
->where(
|
||||
$expr->eq('shareHousehold', true)
|
||||
)
|
||||
->orderBy(['startDate' => Criteria::DESC]);
|
||||
->orderBy(['startDate' => Criteria::DESC, 'id' => Criteria::DESC]);
|
||||
|
||||
return $this->getHouseholdParticipations()
|
||||
->matching($criteria);
|
||||
|
@@ -0,0 +1,60 @@
|
||||
<?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\Form;
|
||||
|
||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||
use Chill\MainBundle\Form\Type\CommentType;
|
||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
|
||||
use Chill\PersonBundle\Repository\Household\HouseholdCompositionTypeRepository;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class HouseholdCompositionType extends AbstractType
|
||||
{
|
||||
private HouseholdCompositionTypeRepository $householdCompositionTypeRepository;
|
||||
|
||||
private TranslatableStringHelperInterface $translatableStringHelper;
|
||||
|
||||
public function __construct(HouseholdCompositionTypeRepository $householdCompositionTypeRepository, TranslatableStringHelperInterface $translatableStringHelper)
|
||||
{
|
||||
$this->householdCompositionTypeRepository = $householdCompositionTypeRepository;
|
||||
$this->translatableStringHelper = $translatableStringHelper;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$types = $this->householdCompositionTypeRepository->findAllActive();
|
||||
|
||||
$builder
|
||||
->add('householdCompositionType', EntityType::class, [
|
||||
'class' => \Chill\PersonBundle\Entity\Household\HouseholdCompositionType::class,
|
||||
'choices' => $types,
|
||||
'choice_label' => function (\Chill\PersonBundle\Entity\Household\HouseholdCompositionType $type) {
|
||||
return $this->translatableStringHelper->localize($type->getLabel());
|
||||
},
|
||||
'label' => 'household_composition.Household composition',
|
||||
])
|
||||
->add('startDate', ChillDateType::class, [
|
||||
'required' => true,
|
||||
'input' => 'datetime_immutable',
|
||||
])
|
||||
->add('numberOfChildren', IntegerType::class, [
|
||||
'required' => true,
|
||||
'label' => 'household_composition.numberOfChildren',
|
||||
])
|
||||
->add('comment', CommentType::class, [
|
||||
'required' => false,
|
||||
]);
|
||||
}
|
||||
}
|
@@ -29,6 +29,8 @@ class MembersEditor
|
||||
{
|
||||
public const VALIDATION_GROUP_AFFECTED = 'household_memberships';
|
||||
|
||||
public const VALIDATION_GROUP_COMPOSITION = 'household_composition';
|
||||
|
||||
public const VALIDATION_GROUP_CREATED = 'household_memberships_created';
|
||||
|
||||
private ?Household $household = null;
|
||||
@@ -77,6 +79,15 @@ class MembersEditor
|
||||
$this->oldMembershipsHashes[] = spl_object_hash($participation);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($person->getHouseholdParticipationsNotShareHousehold() as $participation) {
|
||||
if ($participation->getHousehold() === $this->household
|
||||
&& $participation->getEndDate() === null || $participation->getEndDate() > $membership->getStartDate()
|
||||
&& $participation->getStartDate() <= $membership->getStartDate()
|
||||
) {
|
||||
$participation->setEndDate($membership->getStartDate());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->membershipsAffected[] = $membership;
|
||||
@@ -129,7 +140,7 @@ class MembersEditor
|
||||
{
|
||||
if ($this->hasHousehold()) {
|
||||
$list = $this->validator
|
||||
->validate($this->getHousehold(), null, [self::VALIDATION_GROUP_AFFECTED]);
|
||||
->validate($this->getHousehold(), null, [self::VALIDATION_GROUP_AFFECTED, self::VALIDATION_GROUP_COMPOSITION]);
|
||||
} else {
|
||||
$list = new ConstraintViolationList();
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@ class HouseholdMenuBuilder implements LocalMenuBuilderInterface
|
||||
|
||||
public function buildMenu($menuId, MenuItem $menu, array $parameters): void
|
||||
{
|
||||
/** @var \Chill\PersonBundle\Entity\Household\Household $household */
|
||||
$household = $parameters['household'];
|
||||
|
||||
$menu->addChild($this->translator->trans('household.Household summary'), [
|
||||
@@ -38,6 +39,20 @@ class HouseholdMenuBuilder implements LocalMenuBuilderInterface
|
||||
], ])
|
||||
->setExtras(['order' => 10]);
|
||||
|
||||
$menu->addChild($this->translator->trans('household.Relationship'), [
|
||||
'route' => 'chill_person_household_relationship',
|
||||
'routeParameters' => [
|
||||
'household_id' => $household->getId(),
|
||||
], ])
|
||||
->setExtras(['order' => 15]);
|
||||
|
||||
$menu->addChild($this->translator->trans('household_composition.Compositions'), [
|
||||
'route' => 'chill_person_household_composition_index',
|
||||
'routeParameters' => [
|
||||
'id' => $household->getId(),
|
||||
], ])
|
||||
->setExtras(['order' => 17]);
|
||||
|
||||
$menu->addChild($this->translator->trans('household.Accompanying period'), [
|
||||
'route' => 'chill_person_household_accompanying_period',
|
||||
'routeParameters' => [
|
||||
@@ -51,13 +66,6 @@ class HouseholdMenuBuilder implements LocalMenuBuilderInterface
|
||||
'household_id' => $household->getId(),
|
||||
], ])
|
||||
->setExtras(['order' => 30]);
|
||||
|
||||
$menu->addChild($this->translator->trans('household.Relationship'), [
|
||||
'route' => 'chill_person_household_relationship',
|
||||
'routeParameters' => [
|
||||
'household_id' => $household->getId(),
|
||||
], ])
|
||||
->setExtras(['order' => 15]);
|
||||
}
|
||||
|
||||
public static function getMenuIds(): array
|
||||
|
@@ -0,0 +1,61 @@
|
||||
<?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\Repository\AccompanyingPeriod;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\Persistence\ObjectRepository;
|
||||
|
||||
class AccompanyingPeriodWorkEvaluationRepository implements ObjectRepository
|
||||
{
|
||||
private EntityRepository $repository;
|
||||
|
||||
public function __construct(EntityManagerInterface $entityManager)
|
||||
{
|
||||
$this->repository = $entityManager->getRepository(AccompanyingPeriodWorkEvaluation::class);
|
||||
}
|
||||
|
||||
public function find($id): ?AccompanyingPeriodWorkEvaluation
|
||||
{
|
||||
return $this->repository->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|AccompanyingPeriodWorkEvaluation[]
|
||||
*/
|
||||
public function findAll(): array
|
||||
{
|
||||
return $this->repository->findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null|mixed $limit
|
||||
* @param null|mixed $offset
|
||||
*
|
||||
* @return array|AccompanyingPeriodWorkEvaluation[]
|
||||
*/
|
||||
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array
|
||||
{
|
||||
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
|
||||
}
|
||||
|
||||
public function findOneBy(array $criteria): ?AccompanyingPeriodWorkEvaluation
|
||||
{
|
||||
return $this->findOneBy($criteria);
|
||||
}
|
||||
|
||||
public function getClassName()
|
||||
{
|
||||
return AccompanyingPeriodWorkEvaluation::class;
|
||||
}
|
||||
}
|
@@ -39,7 +39,7 @@ final class HouseholdACLAwareRepository implements HouseholdACLAwareRepositoryIn
|
||||
{
|
||||
$centers = $this->authorizationHelper->getReachableCenters(
|
||||
$this->security->getUser(),
|
||||
HouseholdVoter::SHOW
|
||||
HouseholdVoter::SEE
|
||||
);
|
||||
|
||||
if ([] === $centers) {
|
||||
|
@@ -0,0 +1,75 @@
|
||||
<?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\Repository\Household;
|
||||
|
||||
use Chill\PersonBundle\Entity\Household\Household;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdComposition;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\Persistence\ObjectRepository;
|
||||
|
||||
class HouseholdCompositionRepository implements ObjectRepository
|
||||
{
|
||||
private EntityRepository $repository;
|
||||
|
||||
public function __construct(EntityManagerInterface $entityManager)
|
||||
{
|
||||
$this->repository = $entityManager->getRepository(HouseholdComposition::class);
|
||||
}
|
||||
|
||||
public function countByHousehold(Household $household): int
|
||||
{
|
||||
return $this->repository->count(['household' => $household]);
|
||||
}
|
||||
|
||||
public function find($id): ?HouseholdComposition
|
||||
{
|
||||
return $this->repository->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|HouseholdComposition[]
|
||||
*/
|
||||
public function findAll(): array
|
||||
{
|
||||
return $this->repository->findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
*
|
||||
* @return array|object[]|HouseholdComposition[]
|
||||
*/
|
||||
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array
|
||||
{
|
||||
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|HouseholdComposition[]|object[]
|
||||
*/
|
||||
public function findByHousehold(Household $household, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
|
||||
{
|
||||
return $this->findBy(['household' => $household], $orderBy, $limit, $offset);
|
||||
}
|
||||
|
||||
public function findOneBy(array $criteria): ?HouseholdComposition
|
||||
{
|
||||
return $this->repository->findOneBy($criteria);
|
||||
}
|
||||
|
||||
public function getClassName(): string
|
||||
{
|
||||
return HouseholdComposition::class;
|
||||
}
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
<?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\Repository\Household;
|
||||
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdCompositionType;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Doctrine\Persistence\ObjectRepository;
|
||||
|
||||
class HouseholdCompositionTypeRepository implements ObjectRepository
|
||||
{
|
||||
private EntityRepository $repository;
|
||||
|
||||
public function __construct(EntityManagerInterface $entityManager)
|
||||
{
|
||||
$this->repository = $entityManager->getRepository(HouseholdCompositionType::class);
|
||||
}
|
||||
|
||||
public function find($id): ?HouseholdCompositionType
|
||||
{
|
||||
return $this->repository->find($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|HouseholdCompositionType[]|object[]
|
||||
*/
|
||||
public function findAll(): array
|
||||
{
|
||||
return $this->repository->findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|HouseholdCompositionType[]
|
||||
*/
|
||||
public function findAllActive(): array
|
||||
{
|
||||
return $this->findBy(['active' => true]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $limit
|
||||
* @param $offset
|
||||
*
|
||||
* @return array|HouseholdCompositionType[]|object[]
|
||||
*/
|
||||
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array
|
||||
{
|
||||
return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
|
||||
}
|
||||
|
||||
public function findOneBy(array $criteria): ?HouseholdCompositionType
|
||||
{
|
||||
return $this->repository->findOneBy($criteria);
|
||||
}
|
||||
|
||||
public function getClassName(): string
|
||||
{
|
||||
return HouseholdCompositionType::class;
|
||||
}
|
||||
}
|
@@ -241,7 +241,17 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<!--
|
||||
FAIT REPETER tout le template de App.vue plusieurs fois
|
||||
<li>
|
||||
<pick-workflow
|
||||
relatedEntityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork"
|
||||
:relatedEntityId="this.work.id"
|
||||
:workflows="this.workflows"
|
||||
></pick-workflow>
|
||||
</li>
|
||||
-->
|
||||
|
||||
<li v-if="!isPosting">
|
||||
<button class="btn btn-save" @click="submit">
|
||||
@@ -270,6 +280,7 @@ import AddressRenderBox from 'ChillMainAssets/vuejs/_components/Entity/AddressRe
|
||||
import ThirdPartyRenderBox from 'ChillThirdPartyAssets/vuejs/_components/Entity/ThirdPartyRenderBox.vue';
|
||||
import PickTemplate from 'ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue';
|
||||
import OnTheFly from 'ChillMainAssets/vuejs/OnTheFly/components/OnTheFly.vue';
|
||||
import PickWorkflow from 'ChillMainAssets/vuejs/_components/EntityWorkflow/PickWorkflow.vue';
|
||||
|
||||
const i18n = {
|
||||
messages: {
|
||||
@@ -317,6 +328,7 @@ export default {
|
||||
AddressRenderBox,
|
||||
ThirdPartyRenderBox,
|
||||
PickTemplate,
|
||||
PickWorkflow,
|
||||
OnTheFly
|
||||
},
|
||||
i18n,
|
||||
@@ -347,11 +359,11 @@ export default {
|
||||
display: false
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
computed: {
|
||||
...mapState([
|
||||
'work',
|
||||
'resultsForAction',
|
||||
'evaluationsForAction',
|
||||
|
@@ -1,12 +1,21 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="item-title">
|
||||
<div class="item-title" :title="evaluation.id || 'no id yet'">
|
||||
<span>{{ evaluation.evaluation.title.fr }}</span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<form-evaluation ref="FormEvaluation" :key="evaluation.key" :evaluation="evaluation"></form-evaluation>
|
||||
<ul class="record_actions">
|
||||
|
||||
<ul class="record_actions">
|
||||
<li v-if="evaluation.workflows_availables.length > 0">
|
||||
<pick-workflow
|
||||
relatedEntityClass="faked"
|
||||
:relatedEntityId="evaluation.id"
|
||||
:workflowsAvailables="evaluation.workflows_availables"
|
||||
@goToGenerateWorkflow="goToGenerateWorkflow"
|
||||
></pick-workflow>
|
||||
</li>
|
||||
<li>
|
||||
<a class="btn btn-delete" @click="modal.showModal = true" :title="$t('action.delete')"></a>
|
||||
</li>
|
||||
@@ -34,6 +43,8 @@
|
||||
<script>
|
||||
import FormEvaluation from './FormEvaluation.vue';
|
||||
import Modal from 'ChillMainAssets/vuejs/_components/Modal';
|
||||
import PickWorkflow from 'ChillMainAssets/vuejs/_components/EntityWorkflow/PickWorkflow.vue';
|
||||
import {buildLinkCreate} from 'ChillMainAssets/lib/entity-workflow/api.js';
|
||||
|
||||
const i18n = {
|
||||
messages: {
|
||||
@@ -60,7 +71,8 @@ export default {
|
||||
name: "AddEvaluation",
|
||||
components: {
|
||||
FormEvaluation,
|
||||
Modal
|
||||
Modal,
|
||||
PickWorkflow,
|
||||
},
|
||||
props: ['evaluation'],
|
||||
i18n,
|
||||
@@ -88,10 +100,19 @@ export default {
|
||||
submitForm() {
|
||||
this.toggleEditEvaluation();
|
||||
},
|
||||
buildEditLink(storedObject) {
|
||||
return `/edit/${storedObject.uuid}?returnPath=` + encodeURIComponent(
|
||||
window.location.pathname + window.location.search + window.location.hash);
|
||||
},
|
||||
goToGenerateWorkflow({event, link, workflowName}) {
|
||||
event.preventDefault();
|
||||
console.log(event, link, workflowName);
|
||||
|
||||
const callback = (data) => {
|
||||
let evaluationId = data.accompanyingPeriodWorkEvaluations.find(e => e.key === this.evaluation.key).id;
|
||||
window.location.assign(buildLinkCreate(workflowName,
|
||||
'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluation', evaluationId));
|
||||
};
|
||||
|
||||
return this.$store.dispatch('submit', callback)
|
||||
.catch(e => { console.log(e); throw e; });
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@@ -61,6 +61,32 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="evaluation.documents.length > 0" class="row mb-3">
|
||||
<h5>{{ $t('Documents') }} :</h5>
|
||||
|
||||
<div class="flex-table">
|
||||
<div class="item-bloc" v-for="d in evaluation.documents">
|
||||
<div class="item-row">
|
||||
<div class="item-col"><h6>{{ d.template.name.fr }}</h6></div>
|
||||
<div class="item-col">
|
||||
<p>Créé par {{ d.createdBy.text }}<br/>
|
||||
Le {{ $d(ISOToDatetime(d.createdAt.datetime), 'long') }}</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-row">
|
||||
<ul class="record_actions" >
|
||||
<li>
|
||||
<a :href="buildEditLink(d.storedObject)" class="btn btn-action btn-sm">
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<pick-template
|
||||
entityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation"
|
||||
@@ -99,7 +125,8 @@ const i18n = {
|
||||
evaluation_generate_a_document: "Générer un document",
|
||||
evaluation_choose_a_template: "Choisir un gabarit",
|
||||
evaluation_add_a_document: "Ajouter un document",
|
||||
evaluation_add: "Ajouter une évaluation"
|
||||
evaluation_add: "Ajouter une évaluation",
|
||||
Documents: "Documents",
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -163,6 +190,7 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
ISOToDatetime,
|
||||
listAllStatus() {
|
||||
console.log('load all status');
|
||||
let url = `/api/`;
|
||||
@@ -175,7 +203,11 @@ export default {
|
||||
})
|
||||
;
|
||||
},
|
||||
submitBeforeGenerate() {
|
||||
buildEditLink(storedObject) {
|
||||
return `/wopi/edit/${storedObject.uuid}?returnPath=` + encodeURIComponent(
|
||||
window.location.pathname + window.location.search + window.location.hash);
|
||||
},
|
||||
submitBeforeGenerate() {
|
||||
const callback = (data) => {
|
||||
let evaluationId = data.accompanyingPeriodWorkEvaluations.find(e => e.key === this.evaluation.key).id;
|
||||
return Promise.resolve({entityId: evaluationId});
|
||||
|
@@ -205,6 +205,7 @@ const store = createStore({
|
||||
warningInterval: null,
|
||||
comment: "",
|
||||
editEvaluation: true,
|
||||
workflows_availables: state.work.workflows_availables_evaluation,
|
||||
};
|
||||
state.evaluationsPicked.push(e);
|
||||
},
|
||||
@@ -371,7 +372,8 @@ const store = createStore({
|
||||
if (typeof(callback) !== 'undefined') {
|
||||
return callback(data);
|
||||
} else {
|
||||
console.info('nothing to do here, bye bye');window.location.assign(`/fr/person/accompanying-period/${state.work.accompanyingPeriod.id}/work`);
|
||||
console.info('nothing to do here, bye bye');
|
||||
window.location.assign(`/fr/person/accompanying-period/${state.work.accompanyingPeriod.id}/work`);
|
||||
}
|
||||
}).catch(error => {
|
||||
console.log('error on submit', error);
|
||||
|
@@ -32,7 +32,7 @@
|
||||
</button>
|
||||
</li>
|
||||
<li v-else>
|
||||
<button class="btn btn-save" @click="confirm" :disabled="hasWarnings">
|
||||
<button class="btn btn-save" @click="confirm" :disabled="hasWarnings || !lastStepIsSaveAllowed">
|
||||
{{ $t('household_members_editor.app.save') }}
|
||||
</button>
|
||||
</li>
|
||||
@@ -104,6 +104,13 @@ export default {
|
||||
|
||||
return false;
|
||||
},
|
||||
lastStepIsSaveAllowed() {
|
||||
let r = !this.$store.getters.isHouseholdNew ||
|
||||
(this.$store.state.numberOfChildren !== null && this.$store.state.householdCompositionType !== null);
|
||||
console.log('is saved allowed ?', r);
|
||||
|
||||
return r;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
goToNext() {
|
||||
|
@@ -7,18 +7,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<p>
|
||||
{{ $t('household_members_editor.concerned.persons_will_be_moved') }} :
|
||||
<span v-for="c in concerned" :key="c.person.id">
|
||||
<person-render-box render="badge" :options="{addLink: false}" :person="c.person"></person-render-box>
|
||||
<button class="btn" @click="removePerson(c.person)" v-if="c.allowRemove" style="padding-left:0;">
|
||||
<span class="fa-stack fa-lg" :title="$t('household_members_editor.concerned.remove_concerned')">
|
||||
<i class="fa fa-circle fa-stack-1x text-danger"></i>
|
||||
<i class="fa fa-times fa-stack-1x"></i>
|
||||
</span>
|
||||
</button>
|
||||
</span>
|
||||
</p>
|
||||
<p>{{ $t('household_members_editor.concerned.persons_will_be_moved') }} :</p>
|
||||
|
||||
<ul class="list-suggest remove-items inline">
|
||||
<li v-for="c in concerned" :key="c.person.id" @click="removeConcerned(c)">
|
||||
<span>{{ c.person.text }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="alert alert-info" v-if="concernedPersonsWithHouseholds.length > 0">
|
||||
<p>{{ $t('household_members_editor.concerned.persons_with_household') }}</p>
|
||||
<ul v-for="c in concernedPersonsWithHouseholds" :key="c.person.id">
|
||||
@@ -108,9 +104,14 @@ export default {
|
||||
this.$refs.addPersons.resetSearch(); // to cast child method
|
||||
modal.showModal = false;
|
||||
},
|
||||
removePerson(person) {
|
||||
console.log('remove person in concerned', person);
|
||||
this.$store.dispatch('removePerson', person);
|
||||
removeConcerned(concerned) {
|
||||
console.log('removedconcerned', concerned);
|
||||
|
||||
if (!concerned.allowRemove) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$store.dispatch('removePerson', concerned.person);
|
||||
},
|
||||
makeHouseholdLink(id) {
|
||||
return `/fr/person/household/${id}/summary`
|
||||
|
@@ -4,17 +4,38 @@
|
||||
|
||||
<h2>{{ $t('household_members_editor.dates.dates_title') }}</h2>
|
||||
|
||||
<p>
|
||||
<label for="start_date">
|
||||
<div class="mb-3 row">
|
||||
<label for="start_date" class="col-form-label col-sm-4 required">
|
||||
{{ $t('household_members_editor.dates.start_date') }}
|
||||
</label>
|
||||
<input type="date" v-model="startDate" />
|
||||
</p>
|
||||
<div class="col-sm-8">
|
||||
<input type="date" v-model="startDate" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="this.isHouseholdNew">
|
||||
<h2>{{ $t('household_members_editor.composition.composition') }}</h2>
|
||||
<div class="mb-3 row">
|
||||
<label class="col-form-label col-sm-4 required">{{ $t('household_members_editor.composition.household_composition') }}</label>
|
||||
<div class="col-sm-8">
|
||||
<select v-model="householdCompositionType" class="form-select form-control">
|
||||
<option v-for="t in householdCompositionTypes" :key="t.id" :value="t.id">{{ t.label.fr }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3 row">
|
||||
<label class="col-form-label col-sm-4 required">{{ $t('household_members_editor.composition.number_of_children') }}</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" v-model="numberOfChildren" min="0" max="30" class="form-control"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import CurrentHousehold from "./CurrentHousehold";
|
||||
import {mapGetters, mapState} from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'Dates',
|
||||
@@ -22,6 +43,27 @@ export default {
|
||||
CurrentHousehold
|
||||
},
|
||||
computed: {
|
||||
...mapState(['householdCompositionTypes']),
|
||||
...mapGetters(['isHouseholdNew']),
|
||||
householdCompositionType: {
|
||||
get() {
|
||||
if (this.$store.state.householdCompositionType !== null) {
|
||||
return this.$store.state.householdCompositionType.id;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('setHouseholdCompositionType', value);
|
||||
},
|
||||
},
|
||||
numberOfChildren: {
|
||||
get() {
|
||||
return this.$store.state.numberOfChildren;
|
||||
},
|
||||
set(value) {
|
||||
this.$store.commit('setNumberOfChildren', value);
|
||||
}
|
||||
},
|
||||
startDate: {
|
||||
get() {
|
||||
return [
|
||||
|
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<ckeditor
|
||||
name="content"
|
||||
v-bind:placeholder="$t('comment.content')"
|
||||
:editor="editor"
|
||||
v-model="content"
|
||||
tag-name="textarea">
|
||||
</ckeditor>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CKEditor from '@ckeditor/ckeditor5-vue';
|
||||
import ClassicEditor from "ChillMainAssets/module/ckeditor5";
|
||||
|
||||
export default {
|
||||
name: "PersonComment.vue",
|
||||
components: {
|
||||
ckeditor: CKEditor.component,
|
||||
},
|
||||
props: ['conc'],
|
||||
data() {
|
||||
return {
|
||||
editor: ClassicEditor,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
content: {
|
||||
get() {
|
||||
return this.$props.conc.comment || '';
|
||||
},
|
||||
set(value) {
|
||||
console.log('set content', value);
|
||||
this.$store.commit('setComment', {conc: this.$props.conc, comment: value})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@@ -3,15 +3,15 @@
|
||||
|
||||
<h2>{{ $t('household_members_editor.positioning.persons_to_positionnate')}}</h2>
|
||||
|
||||
<div class="list-household-members">
|
||||
<div class="list-household-members flex-table">
|
||||
<div
|
||||
v-for="conc in concerned"
|
||||
class="item-bloc"
|
||||
v-bind:key="conc.person.id"
|
||||
>
|
||||
<div class="pick-position">
|
||||
<div class="pick-position item-row">
|
||||
<div class="person">
|
||||
<person-render-box render="badge" :options="{}" :person="conc.person"></person-render-box>
|
||||
<h3>{{ conc.person.text }}</h3>
|
||||
</div>
|
||||
<div class="holder">
|
||||
<button
|
||||
@@ -37,6 +37,12 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-row">
|
||||
<div>
|
||||
<h6>{{ $t('household_members_editor.positioning.comment') }}</h6>
|
||||
<person-comment :conc="conc"></person-comment>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -46,12 +52,14 @@ import MemberDetails from './MemberDetails.vue';
|
||||
import {mapGetters, mapState} from "vuex";
|
||||
import CurrentHousehold from "./CurrentHousehold";
|
||||
import PersonRenderBox from 'ChillPersonAssets/vuejs/_components/Entity/PersonRenderBox.vue';
|
||||
import PersonComment from './PersonComment';
|
||||
|
||||
export default {
|
||||
name: "Positioning",
|
||||
components: {
|
||||
CurrentHousehold,
|
||||
PersonRenderBox,
|
||||
PersonComment,
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
|
@@ -52,6 +52,7 @@ const appMessages = {
|
||||
positioning: {
|
||||
persons_to_positionnate: 'Usagers à positionner',
|
||||
holder: "Titulaire",
|
||||
comment: "Commentaire",
|
||||
},
|
||||
app: {
|
||||
next: 'Suivant',
|
||||
@@ -77,7 +78,12 @@ const appMessages = {
|
||||
dates: {
|
||||
start_date: "Début de validité",
|
||||
end_date: "Fin de validité",
|
||||
dates_title: "Période de validité",
|
||||
dates_title: "Depuis le",
|
||||
},
|
||||
composition: {
|
||||
composition: "Composition familiale",
|
||||
household_composition: "Composition du ménage",
|
||||
number_of_children: "Nombre d'enfants mineurs au sein du ménage",
|
||||
},
|
||||
confirmation: {
|
||||
save: "Enregistrer",
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { createStore } from 'vuex';
|
||||
import { householdMove, fetchHouseholdSuggestionByAccompanyingPeriod, fetchAddressSuggestionByPerson} from './../api.js';
|
||||
import { fetchResults } from 'ChillMainAssets/lib/api/apiMethods.js'
|
||||
import { fetchHouseholdByAddressReference } from 'ChillPersonAssets/lib/household.js';
|
||||
import { datetimeToISO } from 'ChillMainAssets/chill/js/date.js';
|
||||
|
||||
@@ -54,8 +55,11 @@ const store = createStore({
|
||||
*/
|
||||
householdSuggestionByAccompanyingPeriod: [], // TODO rename into householdsSuggestion
|
||||
showHouseholdSuggestion: window.household_members_editor_expand_suggestions === 1,
|
||||
householdCompositionType: null,
|
||||
numberOfChildren: 0,
|
||||
addressesSuggestion: [],
|
||||
showAddressSuggestion: true,
|
||||
householdCompositionTypes: [],
|
||||
warnings: [],
|
||||
errors: []
|
||||
},
|
||||
@@ -250,7 +254,8 @@ const store = createStore({
|
||||
payload_conc,
|
||||
payload = {
|
||||
concerned: [],
|
||||
destination: null
|
||||
destination: null,
|
||||
composition: null,
|
||||
}
|
||||
;
|
||||
|
||||
@@ -261,7 +266,6 @@ const store = createStore({
|
||||
};
|
||||
|
||||
if (getters.isHouseholdNew && state.household.current_address !== null) {
|
||||
console.log(state.household);
|
||||
payload.destination.forceAddress = { id: state.household.current_address.address_id };
|
||||
}
|
||||
}
|
||||
@@ -290,6 +294,19 @@ const store = createStore({
|
||||
payload.concerned.push(payload_conc);
|
||||
}
|
||||
|
||||
if (getters.isHouseholdNew) {
|
||||
payload.composition = {
|
||||
household_composition_type: {
|
||||
type: state.householdCompositionType.type,
|
||||
id: state.householdCompositionType.id,
|
||||
},
|
||||
number_of_children: state.numberOfChildren,
|
||||
start_date: {
|
||||
datetime: datetimeToISO(state.startDate),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return payload;
|
||||
},
|
||||
},
|
||||
@@ -409,6 +426,15 @@ const store = createStore({
|
||||
setErrors(state, errors) {
|
||||
state.errors = errors;
|
||||
},
|
||||
setHouseholdCompositionTypes(state, types) {
|
||||
state.householdCompositionTypes = types;
|
||||
},
|
||||
setHouseholdCompositionType(state, id) {
|
||||
state.householdCompositionType = state.householdCompositionTypes.find(t => t.id = id);
|
||||
},
|
||||
setNumberOfChildren(state, number) {
|
||||
state.numberOfChildren = Number.parseInt(number);
|
||||
},
|
||||
addAddressesSuggestion(state, addresses) {
|
||||
let existingIds = state.addressesSuggestion
|
||||
.map(a => a.address_id);
|
||||
@@ -570,4 +596,8 @@ if (concerned.length > 0) {
|
||||
});
|
||||
}
|
||||
|
||||
fetchResults(`/api/1.0/person/houehold/composition/type.json`).then(types => {
|
||||
store.commit('setHouseholdCompositionTypes', types);
|
||||
})
|
||||
|
||||
export { store };
|
||||
|
@@ -7,7 +7,7 @@
|
||||
{% import '@ChillPerson/AccompanyingCourse/Comment/macro_showItem.html.twig' as m %}
|
||||
|
||||
{% macro recordAction(comment, isPinned) %}
|
||||
{% if isPinned is defined and isPinned == 'true' %}
|
||||
{% if isPinned is defined and isPinned == true %}
|
||||
{% else %}
|
||||
<li>
|
||||
<form method="post" action="{{ chill_path_forward_return_path('chill_person_accompanying_period_comment_pin', {'id': comment.id}) }}">
|
||||
@@ -66,8 +66,8 @@
|
||||
{{ _self.form_comment('edit', edit_form) }}
|
||||
{% else %}
|
||||
{{ m.show_comment(accompanyingCourse.pinnedComment, {
|
||||
'pinned': 'true',
|
||||
'recordAction': _self.recordAction(accompanyingCourse.pinnedComment, 'true')
|
||||
'pinned': true,
|
||||
'recordAction': _self.recordAction(accompanyingCourse.pinnedComment, true)
|
||||
}) }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
@@ -1,23 +1,25 @@
|
||||
{%- set countPersonLocation = accompanyingCourse.availablePersonLocation|length -%}
|
||||
{%- set hasPersonLocation = countPersonLocation > 0 -%}
|
||||
<div class="alert alert-danger {% if hasPersonLocation %}alert-with-actions{% endif %}">
|
||||
<div class="float-button bottom"><div class="box">
|
||||
<div class="action">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="btn btn-sm btn-update change-icon"
|
||||
href="{{ path('chill_person_accompanying_course_edit', { 'accompanying_period_id': accompanyingCourse.id, '_fragment': 'section-20' }) }}">
|
||||
<i class="fa fa-fw fa-crosshairs"></i>
|
||||
{{ 'fix it'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="float-button bottom">
|
||||
<div class="box">
|
||||
<div class="action">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="btn btn-sm btn-update change-icon"
|
||||
href="{{ path('chill_person_accompanying_course_edit', { 'accompanying_period_id': accompanyingCourse.id, '_fragment': 'section-20' }) }}">
|
||||
<i class="fa fa-fw fa-crosshairs"></i>
|
||||
{{ 'fix it'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
{{ 'This course is located at a temporarily address. You should locate this course to an user'|trans }}</p>
|
||||
{% if not hasPersonLocation %}
|
||||
<p>
|
||||
{{ 'Associate at least one member with an household, and set an address to this household'|trans }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<p>
|
||||
{{ 'This course is located at a temporarily address. You should locate this course to an user'|trans }}</p>
|
||||
{% if not hasPersonLocation %}
|
||||
<p>
|
||||
{{ 'Associate at least one member with an household, and set an address to this household'|trans }}</p>
|
||||
{% endif %}
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: type, id: entity.id },
|
||||
buttonText: entity|chill_entity_render_string,
|
||||
isDead: entity.deathdate is not null,
|
||||
isDead: entity.deathdate is defined and entity.deathdate is not null,
|
||||
parent: parent
|
||||
} %}
|
||||
{% endmacro %}
|
||||
@@ -212,16 +212,13 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block block_post_menu %}
|
||||
<div class="post-menu pt-4">
|
||||
|
||||
<div class="d-grid gap-2">
|
||||
<a class="btn btn-primary" href="{{ chill_path_add_return_path('chill_main_notification_create', {'entityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod', 'entityId': accompanyingCourse.id}) }}">
|
||||
<i class="fa fa-paper-plane fa-fw"></i>
|
||||
{{ 'notification.Notify'|trans }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{{ chill_list_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', accompanyingCourse.id) }}
|
||||
|
||||
<div class="post-menu pt-4">
|
||||
<div class="d-grid gap-2">
|
||||
<a class="btn btn-primary" href="{{ chill_path_add_return_path('chill_main_notification_create', {'entityClass': 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod', 'entityId': accompanyingCourse.id}) }}">
|
||||
<i class="fa fa-paper-plane fa-fw"></i>
|
||||
{{ 'notification.Notify'|trans }}
|
||||
</a>
|
||||
</div>
|
||||
{{ chill_list_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', accompanyingCourse.id) }}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@@ -0,0 +1,127 @@
|
||||
<div class="item-bloc accompanying_course_work-item{% if itemBlocClass is defined %} {{ itemBlocClass }}{% endif %}">
|
||||
|
||||
<div class="item-row">
|
||||
<h2 class="badge-title">
|
||||
<span class="title_label"></span>
|
||||
<span class="title_action">{{ w.socialAction|chill_entity_render_string }}
|
||||
|
||||
<ul class="small_in_title columns mt-1">
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.start_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ w.startDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% if w.endDate %}
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ w.endDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="item-row separator">
|
||||
<div class="wrap-list">
|
||||
|
||||
{% if w.createdBy %}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3>{{ 'Referrer'|trans }}</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
<p class="wl-item">
|
||||
{{ w.createdBy|chill_entity_render_box }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{%- if w.persons -%}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3>{{ 'Persons in accompanying course'|trans }}</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
{% for p in w.persons %}
|
||||
<span class="wl-item">
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: 'person', id: p.id },
|
||||
buttonText: p|chill_entity_render_string,
|
||||
isDead: p.deathdate is not null
|
||||
} %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{%- if w.handlingThierParty -%}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3>{{ 'Thirdparty handling'|trans }}</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
<span class="wl-item">
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: 'thirdparty', id: w.handlingThierParty.id },
|
||||
buttonText: w.handlingThierParty|chill_entity_render_string
|
||||
} %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{%- if w.socialAction.issue -%}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3>{{ 'Social issue'|trans }}</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
<p class="wl-item social-issues">
|
||||
{{ w.socialAction.issue|chill_entity_render_box }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-row column">
|
||||
{% include 'ChillPersonBundle:AccompanyingCourseWork:_objectifs_results_evaluations.html.twig' %}
|
||||
</div>
|
||||
|
||||
<div class="item-row separator">
|
||||
<div class="item-col item-meta">
|
||||
{% set notif_counter = chill_count_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', w.id) %}
|
||||
{% if notif_counter.total > 0 %}
|
||||
{{ chill_counter_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', w.id) }}
|
||||
{% endif %}
|
||||
|
||||
{% import '@ChillPerson/Macro/updatedBy.html.twig' as macro %}
|
||||
{{ macro.updatedBy(w) }}
|
||||
</div>
|
||||
|
||||
{% if displayAction is defined and displayAction == true %}
|
||||
<div class="item-col">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="btn btn-edit" title="{{ 'Edit'|trans }}"
|
||||
href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_edit', { 'id': w.id }) }}"
|
||||
></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="btn btn-delete" title="{{ 'Delete'|trans }}"
|
||||
href="{{ path('chill_person_accompanying_period_work_delete', { 'id': w.id } ) }}"
|
||||
></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
</div>
|
@@ -2,27 +2,34 @@
|
||||
|
||||
{% block title 'accompanying_course_work.Edit accompanying course work'|trans %}
|
||||
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('vue_accourse_work_edit') }}
|
||||
{{ encore_entry_link_tags('mod_entity_workflow_pick') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="accompanying_course_work-edit">
|
||||
|
||||
<h1>{{ block('title') }}</h1>
|
||||
|
||||
<div id="accompanying_course_work_edit"></div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block block_post_menu %}
|
||||
<div class="post-menu pt-4">
|
||||
{% set workflows_frame = chill_entity_workflow_list('Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork', work.id) %}
|
||||
{% if workflows_frame is not empty %}
|
||||
{{ workflows_frame|raw }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
{{ parent() }}
|
||||
<script type="text/javascript">
|
||||
window.accompanyingCourseWork = {{ json|json_encode|raw }};
|
||||
window.accompanyingCourseWork = {{ json|json_encode|raw }};
|
||||
</script>
|
||||
|
||||
{{ encore_entry_script_tags('vue_accourse_work_edit') }}
|
||||
{{ encore_entry_script_tags('mod_entity_workflow_pick') }}
|
||||
{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ parent() }}
|
||||
{{ encore_entry_link_tags('vue_accourse_work_edit') }}
|
||||
{% endblock %}
|
||||
|
@@ -18,133 +18,7 @@
|
||||
{% else %}
|
||||
<div class="flex-table accompanying_course_work-list">
|
||||
{% for w in works %}
|
||||
<div class="item-bloc">
|
||||
|
||||
<div class="item-row">
|
||||
<h2 class="badge-title">
|
||||
<span class="title_label"></span>
|
||||
<span class="title_action">{{ w.socialAction|chill_entity_render_string }}
|
||||
|
||||
<ul class="small_in_title columns mt-1">
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.start_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ w.startDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% if w.endDate %}
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ w.endDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
||||
</span>
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="item-row separator">
|
||||
<div class="wrap-list">
|
||||
|
||||
{% if w.createdBy %}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3>{{ 'Referrer'|trans }}</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
<p class="wl-item">
|
||||
{{ w.createdBy|chill_entity_render_box }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{%- if w.persons -%}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3>{{ 'Persons in accompanying course'|trans }}</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
{% for p in w.persons %}
|
||||
<span class="wl-item">
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: 'person', id: p.id },
|
||||
buttonText: p|chill_entity_render_string,
|
||||
isDead: entity.deathdate is not null
|
||||
} %}
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{%- if w.handlingThierParty -%}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3>{{ 'Thirdparty handling'|trans }}</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
<span class="wl-item">
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
action: 'show', displayBadge: true,
|
||||
targetEntity: { name: 'thirdparty', id: w.handlingThierParty.id },
|
||||
buttonText: w.handlingThierParty|chill_entity_render_string,
|
||||
parent: {
|
||||
'type': 'accompanying_period_resource',
|
||||
'id': r.id,
|
||||
'comment': r.comment,
|
||||
'parent': {
|
||||
'type': 'accompanying_period',
|
||||
'id': accompanyingCourse.id
|
||||
}
|
||||
}
|
||||
}
|
||||
%}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{%- if w.socialAction.issue -%}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3>{{ 'Social issue'|trans }}</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
<p class="wl-item social-issues">
|
||||
{{ w.socialAction.issue|chill_entity_render_box }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-row column">
|
||||
{% include 'ChillPersonBundle:AccompanyingCourseWork:_objectifs_results_evaluations.html.twig' with {} %}
|
||||
</div>
|
||||
|
||||
<div class="item-row separator">
|
||||
<div class="updatedBy">
|
||||
{{ 'Last updated by'|trans}} <b>{{ w.updatedBy|chill_entity_render_box }}</b>,<br>
|
||||
{{ 'le ' ~ w.updatedAt|format_datetime('long', 'short') }}
|
||||
</div>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="btn btn-edit" title="{{ 'Edit'|trans }}"
|
||||
href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_edit', { 'id': w.id }) }}"
|
||||
></a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="btn btn-delete" title="{{ 'Delete'|trans }}"
|
||||
href="{{ path('chill_person_accompanying_period_work_delete', { 'id': w.id } ) }}"
|
||||
></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% include '@ChillPerson/AccompanyingCourseWork/_item.html.twig' with { 'displayAction': true } %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@@ -46,16 +46,15 @@
|
||||
{% include 'ChillPersonBundle:AccompanyingCourseWork:_objectifs_results_evaluations.html.twig' with {} %}
|
||||
</ul>
|
||||
|
||||
<div class="metadata text-end" style="font-size: 60%">
|
||||
{{ 'Last updated by'|trans }}
|
||||
<span class="user">{{ w.updatedBy|chill_entity_render_box }}</span>:
|
||||
<span class="date">{{ w.updatedAt|format_datetime('short', 'short') }}</span>
|
||||
<div class="metadata text-end">
|
||||
{% import '@ChillPerson/Macro/updatedBy.html.twig' as macro %}
|
||||
{{ macro.updatedBy(w) }}
|
||||
</div>
|
||||
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</a>{# {{ dump(w) }} #}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
|
@@ -113,11 +113,19 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if recordAction is defined %}
|
||||
<div class="item-row separator">
|
||||
<ul class="record_actions">
|
||||
{{ recordAction }}
|
||||
</ul>
|
||||
<div class="item-row separator">
|
||||
<div class="item-col item-meta">
|
||||
{% set notif_counter = chill_count_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', period.id) %}
|
||||
{% if notif_counter.total > 0 %}
|
||||
{{ chill_counter_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', period.id) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="item-col">
|
||||
{% if recordAction is defined %}
|
||||
<ul class="record_actions">
|
||||
{{ recordAction }}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -4,12 +4,14 @@
|
||||
{% block title 'household.Edit household members'|trans %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-md-10 col-xxl household-members">
|
||||
<div class="row">
|
||||
<div class="col-md-10 col-xxl household-members">
|
||||
|
||||
<h1>{{ block('title') }}</h1>
|
||||
<div id="household_members_editor"></div>
|
||||
<h1>{{ block('title') }}</h1>
|
||||
<div id="household_members_editor"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block js %}
|
||||
|
@@ -51,7 +51,42 @@
|
||||
</div>
|
||||
<div class="item-bloc col-7 col-comment">
|
||||
{% if form is null %}
|
||||
|
||||
{% set currentComposition = household.currentComposition %}
|
||||
{% if currentComposition is not null %}
|
||||
<div>
|
||||
<h6>
|
||||
{{ currentComposition.householdCompositionType.label|localize_translatable_string }}
|
||||
</h6>
|
||||
<p>
|
||||
{{ 'household_composition.numberOfChildren children in household'|trans({'numberOfChildren': currentComposition.numberOfChildren}) }}
|
||||
</p>
|
||||
<p>
|
||||
{{ 'household_composition.Since'|trans({'startDate': currentComposition.startDate}) }}
|
||||
</p>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="btn btn-sm btn-update change-icon"
|
||||
href="{{ path('chill_person_household_composition_index', {'id': household.id}) }}">
|
||||
{{ 'household_composition.Update composition'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-danger">
|
||||
<p>
|
||||
{{ 'household_composition.Currently no composition'|trans }}
|
||||
</p>
|
||||
<ul class="record_actions" style="margin-bottom: 0">
|
||||
<li>
|
||||
<a class="btn btn-sm btn-update change-icon"
|
||||
href="{{ path('chill_person_household_composition_index', {'id': household.id}) }}">
|
||||
{{ 'household_composition.Add a composition'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if household.waitingForBirth or not household.commentMembers.isEmpty() %}
|
||||
<div class="p-4 bg-light">
|
||||
{% if household.waitingForBirth %}
|
||||
@@ -176,13 +211,26 @@
|
||||
<span class="unfolded text-secondary">{{ 'household.Hide memberships'|trans }}</span>
|
||||
</button>
|
||||
</h2>
|
||||
|
||||
{% macro buttonsOldMembers(member) %}
|
||||
{% set household = member.person.getCurrentHousehold %}
|
||||
{% if household is not null %}
|
||||
<li>
|
||||
<a href="{{ path('chill_person_household_summary', { 'household_id': household.id }) }}" class="btn btn-sm btn-chill-beige"><i class="fa fa-home"></i></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
<div id="collapse_{{ p == '_none' ? '_none' : p.id }}"
|
||||
class="accordion-collapse collapse"
|
||||
aria-labelledby="heading_{{ p == '_none' ? '_none' : p.id }}"
|
||||
data-bs-parent="#nonCurrent">
|
||||
<div class="flex-table my-0 list-household-members">
|
||||
{% for m in old_members %}
|
||||
{% include '@ChillPerson/Household/_render_member.html.twig' with { 'member': m } %}
|
||||
{% include '@ChillPerson/Household/_render_member.html.twig' with {
|
||||
'member': m,
|
||||
'customButtons': { 'before': _self.buttonsOldMembers(m) }
|
||||
} %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -0,0 +1,96 @@
|
||||
{% extends '@ChillPerson/Household/layout.html.twig' %}
|
||||
|
||||
{% block title 'household_composition.Compositions'|trans %}
|
||||
|
||||
{% block block_post_menu %}
|
||||
<div class="post-menu"></div>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="household_composition">
|
||||
<h1>{{ block('title') }}</h1>
|
||||
|
||||
{% if compositions|length == 0 %}
|
||||
<p class="chill-no-data-statement">{{ 'household_composition.No composition yet'|trans }}</p>
|
||||
{% else %}
|
||||
<div class="flex-table">
|
||||
{% for c in compositions %}
|
||||
{% if c.id != editId %}
|
||||
<div class="item-bloc">
|
||||
<div class="item-row">
|
||||
<div class="item-col">
|
||||
<h3>{{ c.householdCompositionType.label|localize_translatable_string }}</h3>
|
||||
<p>{{ 'household_composition.numberOfChildren'|trans }}: {{ c.numberOfChildren }}</p>
|
||||
</div>
|
||||
<div class="item-col">{{ 'household_composition.Since'|trans({'startDate': c.startDate}) }}</div>
|
||||
</div>
|
||||
<div class="item-row">
|
||||
<div class="item-col">
|
||||
{% if c.endDate is null %}
|
||||
<span class="chill-no-data-statement">{{ 'household_composition.Still active'|trans }}</span>
|
||||
{% else %}
|
||||
{{ 'household_composition.Until'|trans({'endDate': c.endDate })}}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if c.comment.comment is not empty %}
|
||||
<div class="item-row separator">
|
||||
{{ c.comment|chill_entity_render_box }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if is_granted('CHILL_PERSON_HOUSEHOLD_EDIT', c.household) %}
|
||||
<div class="item-row">
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a href="{{ path('chill_person_household_composition_index', {'id': c.household.id, 'edit': c.id}) }}" class="btn btn-edit"></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{ path('chill_person_household_composition_index', {'id': c.household.id, 'edit': c.id}) }}" class="btn btn-edit"></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
{{ form_start(form) }}
|
||||
|
||||
{{ form_widget(form) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<li class="cancel">
|
||||
<a href="{{ path('chill_person_household_composition_index', {'id': c.household.id}) }}">{{ 'Cancel'|trans }}</a>
|
||||
</li>
|
||||
<li>
|
||||
<button type="submit" class="btn btn-create">{{ 'Save'|trans }}</button>
|
||||
</li>
|
||||
</ul>
|
||||
{{ form_end(form) }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div id="collapseForm" class="{% if not isPosted %}collapse{% endif %}">
|
||||
{{ form_start(form) }}
|
||||
|
||||
{{ form_widget(form) }}
|
||||
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<button type="submit" class="btn btn-create">{{ 'Save'|trans }}</button>
|
||||
</li>
|
||||
</ul>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
|
||||
{% if editId == -1 %}
|
||||
<ul class="record_actions sticky-form-buttons">
|
||||
<li>
|
||||
<button class="btn btn-primary btn-create change-icon" type="button" data-bs-toggle="collapse" data-bs-target="#collapseForm" aria-expanded="false" aria-controls="collapseForm">
|
||||
{{ 'Create'|trans }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
@@ -0,0 +1,12 @@
|
||||
{% macro updatedBy(entity) %}
|
||||
<div class="updatedBy">
|
||||
{{ 'Last updated on'|trans }}
|
||||
<span class="date">
|
||||
{{ entity.updatedAt|format_datetime('medium', 'short') }}
|
||||
</span>,
|
||||
{{ 'by_user'|trans }}
|
||||
<span class="user">
|
||||
{{ entity.updatedBy|chill_entity_render_box }}
|
||||
</span>
|
||||
</div>
|
||||
{% endmacro %}
|
@@ -125,7 +125,7 @@
|
||||
{% if not person.isSharingHousehold() %}
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="btn btn-misc" href="{{chill_path_add_return_path('chill_person_household_members_editor', { 'persons': [ person.id ], 'followAfter': 'true'}) }}">
|
||||
<a class="btn btn-misc" href="{{chill_path_add_return_path('chill_person_household_members_editor', { 'persons': [ person.id ], 'followAfter': true}) }}">
|
||||
<i class="fa fa-sign-in fa-fw"></i>
|
||||
{{ 'household.Join'|trans }}
|
||||
</a>
|
||||
|
@@ -74,133 +74,158 @@
|
||||
{# add as requestor #}
|
||||
|
||||
{% if acps|length > 0 %}
|
||||
<div class="item-row">
|
||||
<div class="wrap-list periods-list">
|
||||
{% for acp in acps %}
|
||||
{% set app = person.findParticipationForPeriod(acp) %}
|
||||
<div class="wl-row separator">
|
||||
{% for acp in acps %}
|
||||
{% set app = person.findParticipationForPeriod(acp) %}
|
||||
<div class="item-row separator">
|
||||
<div class="wrap-list periods-list">
|
||||
|
||||
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<div>
|
||||
{% if acp.emergency %}
|
||||
<span class="badge rounded-pill bg-danger">{{- 'Emergency'|trans|upper -}}</span>
|
||||
{% endif %}
|
||||
{% if acp.confidential %}
|
||||
<span class="badge rounded-pill bg-confidential">{{- 'Confidential'|trans|upper -}}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if acp.step == 'DRAFT' %}
|
||||
<div class="is-draft">
|
||||
<span class="course-draft badge bg-secondary" title="{{ 'course.draft'|trans }}">{{ 'course.draft'|trans }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if acp.requestorPerson == person %}
|
||||
<div>
|
||||
<span class="as-requestor badge bg-info" title="{{ 'Requestor'|trans|e('html_attr') }}">
|
||||
{{ 'Requestor'|trans({'gender': person.gender}) }}
|
||||
</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="date">
|
||||
<h3 class="courseid mb-2">
|
||||
<a href="{{ path('chill_person_accompanying_course_index', { 'accompanying_period_id': acp.id }) }}"
|
||||
title="{{ 'See accompanying period'|trans }}" class="btn btn-outline-primary">
|
||||
<i class="fa fa-random fa-fw"></i>
|
||||
{{ 'File number'|trans }} {{ acp.id }}
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
<div class="d-flex flex-column justify-content-center">
|
||||
{% if app != null %}
|
||||
{{ 'Since %date%'|trans({'%date%': app.startDate|format_date('medium') }) }}
|
||||
<div class="date">
|
||||
{{ 'Since %date%'|trans({'%date%': app.startDate|format_date('medium') }) }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% set notif_counter = chill_count_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', acp.id) %}
|
||||
{% if notif_counter.total > 0 %}
|
||||
{{ chill_counter_notifications('Chill\\PersonBundle\\Entity\\AccompanyingPeriod', acp.id) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if acp.user is not null %}
|
||||
<div class="ms-auto">
|
||||
{% if acp.emergency %}
|
||||
<span class="badge rounded-pill bg-danger">{{- 'Emergency'|trans|upper -}}</span>
|
||||
{% endif %}
|
||||
|
||||
{% if acp.confidential %}
|
||||
<span class="badge rounded-pill bg-confidential">{{- 'Confidential'|trans|upper -}}</span>
|
||||
{% endif %}
|
||||
|
||||
{% if acp.step == 'DRAFT' %}
|
||||
<span class="badge bg-secondary" style="font-size: 85%;" title="{{ 'course.draft'|trans }}">{{ 'course.draft'|trans }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if acp.user is not null %}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3 class="referrer">{{ 'Referrer'|trans }}</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
<div class="user">
|
||||
<abbr class="referrer" title="{{ 'Referrer'|trans }}">ref:</abbr>
|
||||
{{ acp.user|chill_entity_render_box }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="courseid">
|
||||
{{ 'File number'|trans }} {{ acp.id }}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
|
||||
{% for issue in acp.socialIssues %}
|
||||
{{ issue|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
|
||||
<ul class="record_actions record_actions_column">
|
||||
<li>
|
||||
<a href="{{ path('chill_person_accompanying_course_index', { 'accompanying_period_id': acp.id }) }}"
|
||||
class="btn btn-sm btn-outline-primary" title="{{ 'See accompanying period'|trans }}">
|
||||
<i class="fa fa-random fa-fw"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% if acp.currentParticipations|length > 1 %}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<div class="participants">
|
||||
{{ 'Participants'|trans }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
{% set participating = false %}
|
||||
{% for part in acp.currentParticipations %}
|
||||
{% if part.person.id != person.id %}
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
targetEntity: { name: 'person', id: part.person.id },
|
||||
action: 'show',
|
||||
displayBadge: true,
|
||||
buttonText: part.person|chill_entity_render_string,
|
||||
isDead: part.person.deathdate is not null
|
||||
} %}
|
||||
{% else %}
|
||||
{% set participating = true %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if participating %}
|
||||
{{ 'person.and_himself'|trans({'gender': person.gender}) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if (acp.requestorPerson is not null and acp.requestorPerson.id != person.id) or acp.requestorThirdParty is not null %}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<div>
|
||||
{% if acp.requestorPerson is not null %}
|
||||
{{ 'Requestor'|trans({'gender': acp.requestorPerson.gender}) }}
|
||||
{% else %}
|
||||
{{ 'Requestor'|trans({'gender': 'other'})}}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
{% if acp.requestorThirdParty is not null %}
|
||||
|
||||
{% if acp.socialIssues|length > 0 %}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3>{{ 'Social issues'|trans }}</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
{% for issue in acp.socialIssues %}
|
||||
{{ issue|chill_entity_render_box }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# ????
|
||||
{% if acp.requestorPerson == person %}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3>
|
||||
|
||||
</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
<span class="as-requestor badge bg-info" title="{{ 'Requestor'|trans|e('html_attr') }}">
|
||||
{{ 'Requestor'|trans({'gender': person.gender}) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
#}
|
||||
|
||||
{% if acp.currentParticipations|length > 1 %}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3 class="participants">
|
||||
{{ 'Participants'|trans }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
{% set participating = false %}
|
||||
{% for part in acp.currentParticipations %}
|
||||
{% if part.person.id != person.id %}
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
targetEntity: { name: 'person', id: part.person.id },
|
||||
action: 'show',
|
||||
displayBadge: true,
|
||||
buttonText: part.person|chill_entity_render_string,
|
||||
isDead: part.person.deathdate is not null
|
||||
} %}
|
||||
{% else %}
|
||||
{% set participating = true %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if participating %}
|
||||
{{ 'person.and_himself'|trans({'gender': person.gender}) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if (acp.requestorPerson is not null and acp.requestorPerson.id != person.id) or acp.requestorThirdParty is not null %}
|
||||
<div class="wl-row">
|
||||
<div class="wl-col title">
|
||||
<h3>
|
||||
{% if acp.requestorPerson is not null %}
|
||||
{{ 'Requestor'|trans({'gender': acp.requestorPerson.gender}) }}
|
||||
{% else %}
|
||||
{{ 'Requestor'|trans({'gender': 'other'})}}
|
||||
{% endif %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="wl-col list">
|
||||
{% if acp.requestorThirdParty is not null %}
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
targetEntity: { name: 'thirdparty', id: acp.requestorThirdParty.id },
|
||||
action: 'show',
|
||||
displayBadge: true,
|
||||
buttonText: acp.requestorThirdParty|chill_entity_render_string
|
||||
} %}
|
||||
{% else %}
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
targetEntity: { name: 'person', id: acp.requestorPerson.id },
|
||||
action: 'show',
|
||||
displayBadge: true,
|
||||
buttonText: acp.requestorPerson|chill_entity_render_string,
|
||||
isDead: acp.requestorPerson.deathdate is not null
|
||||
} %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
{% include '@ChillMain/OnTheFly/_insert_vue_onthefly.html.twig' with {
|
||||
targetEntity: { name: 'person', id: acp.requestorPerson.id },
|
||||
action: 'show',
|
||||
displayBadge: true,
|
||||
buttonText: acp.requestorPerson|chill_entity_render_string,
|
||||
isDead: acp.requestorPerson.deathdate is not null
|
||||
} %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
@@ -301,10 +301,8 @@ This view should receive those arguments:
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if person.updatedBy %}
|
||||
<div class="updatedBy">
|
||||
{{ 'Last updated by'|trans}}: <b>{{ person.updatedBy|chill_entity_render_box }}</b>,<br>
|
||||
{{ 'on'|trans ~ person.updatedAt|format_datetime('long', 'short') }}
|
||||
</div>
|
||||
{% import '@ChillPerson/Macro/updatedBy.html.twig' as macro %}
|
||||
{{ macro.updatedBy(person) }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
@@ -0,0 +1,17 @@
|
||||
<div class="flex-table accompanying_course_work-list">
|
||||
{% include '@ChillPerson/AccompanyingCourseWork/_item.html.twig' with {
|
||||
'w': work,
|
||||
'itemBlocClass': 'bg-chill-llight-gray'
|
||||
} %}
|
||||
</div>
|
||||
|
||||
{% if display_action is defined and display_action == true %}
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="btn btn-update"
|
||||
href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_edit', { 'id': work.id }) }}">
|
||||
{{ 'Edit'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
@@ -0,0 +1,19 @@
|
||||
{% import '@ChillMain/Workflow/macro_breadcrumb.html.twig' as m %}
|
||||
|
||||
<div class="flex-grow-1 {% if add_classes is defined %}{{ add_classes }}{% else %}h2{% endif %}">
|
||||
<div>
|
||||
{% if concerne is defined and concerne == true %}
|
||||
<span class="item-key">{{ 'Concerne'|trans }}: </span>
|
||||
{% endif %}
|
||||
|
||||
{{ 'workflow.Work (n°%w%)'|trans({'%w%': work.id }) }}
|
||||
|
||||
{% if description is defined and description == true %}
|
||||
{{ ' — ' ~ work.socialAction|chill_entity_render_string }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if breadcrumb is defined and breadcrumb == true %}
|
||||
{{ m.breadcrumb(_context) }}
|
||||
{% endif %}
|
||||
</div>
|
@@ -0,0 +1,99 @@
|
||||
<div class="flex-table accompanying_course_work-list">
|
||||
<div class="item-bloc evaluation-item bg-chill-llight-gray">
|
||||
<div class="item-row mb-2">
|
||||
<h2 class="badge-title">
|
||||
<span class="title_label"></span>
|
||||
<span class="title_action">
|
||||
{{ evaluation.accompanyingPeriodWork.socialAction|chill_entity_render_string }}
|
||||
<ul class="small_in_title columns mt-1">
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.start_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.accompanyingPeriodWork.startDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% if evaluation.accompanyingPeriodWork.endDate %}
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.accompanyingPeriodWork.endDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="item-row column">
|
||||
<table class="obj-res-eval my-3" style="font-size: 110% !important;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="eval">
|
||||
<h4 class="title_label">
|
||||
{{ 'Évaluation'|trans }}
|
||||
</h4>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="eval">
|
||||
<ul class="eval_title">
|
||||
<li class="my-2">
|
||||
{{ evaluation.evaluation.title|localize_translatable_string }}
|
||||
<ul class="columns pt-2">
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.start_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.startDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% if evaluation.endDate %}
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.end_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.endDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if evaluation.maxDate %}
|
||||
<li>
|
||||
<span class="item-key">{{ 'accompanying_course_work.max_date'|trans ~ ' : ' }}</span>
|
||||
<b>{{ evaluation.maxDate|format_date('short') }}</b>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if evaluation.warningInterval and evaluation.warningInterval.d > 0 %}
|
||||
<li>
|
||||
{% set days = (evaluation.warningInterval.d + evaluation.warningInterval.m * 30) %}
|
||||
<span class="item-key">{{ 'accompanying_course_work.warning_interval'|trans ~ ' : ' }}</span>
|
||||
{{ 'accompanying_course_work.%days% days before max_date'|trans({'%days%': days }) }}
|
||||
</li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<span class="item-key">créé par</span>
|
||||
<b>{{ evaluation.createdBy.username }}</b>
|
||||
<span class="item-key">{{ 'le'|trans }}</span>
|
||||
<b>{{ evaluation.createdAt|format_date('short') }}</b>
|
||||
</li>
|
||||
</ul>
|
||||
{% if evaluation.comment %}
|
||||
<blockquote class="chill-user-quote" style="margin-left: 0;">
|
||||
{{ evaluation.comment }}
|
||||
</blockquote>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="item-row">
|
||||
{% import '@ChillPerson/Macro/updatedBy.html.twig' as macro %}
|
||||
{{ macro.updatedBy(evaluation) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if display_action is defined and display_action == true %}
|
||||
{# TODO add acl #}
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<a class="btn btn-show" href="{{ path('chill_person_accompanying_period_work_edit', {'id': evaluation.accompanyingPeriodWork.id}) }}">
|
||||
{{ 'Show'|trans }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
{% endif %}
|
@@ -0,0 +1,19 @@
|
||||
{% import '@ChillMain/Workflow/macro_breadcrumb.html.twig' as m %}
|
||||
|
||||
<div class="flex-grow-1 {% if add_classes is defined %}{{ add_classes }}{% else %}h2{% endif %}">
|
||||
<div>
|
||||
{% if concerne is defined and concerne == true %}
|
||||
<span class="item-key">{{ 'Concerne'|trans }}: </span>
|
||||
{% endif %}
|
||||
|
||||
{{ 'workflow.Evaluation (n°%eval%)'|trans({'%eval%': evaluation.id}) }}
|
||||
|
||||
{% if description is defined and description == true %}
|
||||
{{ ' — ' ~ evaluation.evaluation.title|localize_translatable_string }}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if breadcrumb is defined and breadcrumb == true %}
|
||||
{{ m.breadcrumb(_context) }}
|
||||
{% endif %}
|
||||
</div>
|
@@ -0,0 +1,51 @@
|
||||
<?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\Security\Authorization;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use UnexpectedValueException;
|
||||
|
||||
class AccompanyingPeriodWorkEvaluationVoter extends Voter
|
||||
{
|
||||
public const SEE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_EVALUATION_SHOW';
|
||||
|
||||
private Security $security;
|
||||
|
||||
public function __construct(Security $security)
|
||||
{
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
protected function supports($attribute, $subject)
|
||||
{
|
||||
return $subject instanceof AccompanyingPeriodWorkEvaluation
|
||||
&& self::SEE === $attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $attribute
|
||||
* @param AccompanyingPeriodWorkEvaluation $subject
|
||||
*/
|
||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
|
||||
{
|
||||
switch ($attribute) {
|
||||
case self::SEE:
|
||||
return $this->security->isGranted(AccompanyingPeriodWorkVoter::SEE, $subject->getAccompanyingPeriodWork());
|
||||
|
||||
default:
|
||||
throw new UnexpectedValueException("attribute {$attribute} is not supported");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
<?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\Security\Authorization;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use UnexpectedValueException;
|
||||
use function in_array;
|
||||
|
||||
class AccompanyingPeriodWorkVoter extends Voter
|
||||
{
|
||||
public const SEE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_SEE';
|
||||
|
||||
private Security $security;
|
||||
|
||||
public function __construct(Security $security)
|
||||
{
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
protected function supports($attribute, $subject): bool
|
||||
{
|
||||
return $subject instanceof AccompanyingPeriodWork
|
||||
&& in_array($attribute, $this->getRoles(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $attribute
|
||||
* @param AccompanyingPeriodWork $subject
|
||||
*/
|
||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
|
||||
{
|
||||
switch ($attribute) {
|
||||
case self::SEE:
|
||||
return $this->security->isGranted(AccompanyingPeriodVoter::SEE, $subject->getAccompanyingPeriod());
|
||||
|
||||
default:
|
||||
throw new UnexpectedValueException("attribute {$attribute} is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
private function getRoles(): array
|
||||
{
|
||||
return [self::SEE];
|
||||
}
|
||||
}
|
@@ -11,7 +11,66 @@ declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Security\Authorization;
|
||||
|
||||
class HouseholdVoter
|
||||
use Chill\PersonBundle\Entity\Household\Household;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdMember;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use UnexpectedValueException;
|
||||
use function in_array;
|
||||
|
||||
class HouseholdVoter extends Voter
|
||||
{
|
||||
public const SHOW = PersonVoter::SEE;
|
||||
public const EDIT = 'CHILL_PERSON_HOUSEHOLD_EDIT';
|
||||
|
||||
public const SEE = 'CHILL_PERSON_HOUSEHOLD_SEE';
|
||||
|
||||
/**
|
||||
* @deprecated use @see{self::SEE} instead
|
||||
*/
|
||||
public const SHOW = self::SEE;
|
||||
|
||||
private const ALL = [
|
||||
self::EDIT, self::SEE,
|
||||
];
|
||||
|
||||
private Security $security;
|
||||
|
||||
public function __construct(Security $security)
|
||||
{
|
||||
$this->security = $security;
|
||||
}
|
||||
|
||||
protected function supports($attribute, $subject)
|
||||
{
|
||||
return $subject instanceof Household
|
||||
&& in_array($attribute, self::ALL, true);
|
||||
}
|
||||
|
||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
|
||||
{
|
||||
switch ($attribute) {
|
||||
case self::SEE:
|
||||
return $this->checkAssociatedMembersRole($subject, PersonVoter::SEE);
|
||||
|
||||
case self::EDIT:
|
||||
return $this->checkAssociatedMembersRole($subject, PersonVoter::UPDATE);
|
||||
|
||||
default:
|
||||
throw new UnexpectedValueException('attribute not supported');
|
||||
}
|
||||
}
|
||||
|
||||
private function checkAssociatedMembersRole(Household $household, string $attribute): bool
|
||||
{
|
||||
foreach ($household->getCurrentMembers()->map(static function (HouseholdMember $member) {
|
||||
return $member->getPerson();
|
||||
}) as $person) {
|
||||
if ($this->security->isGranted($attribute, $person)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,74 @@
|
||||
<?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\Serializer\Normalizer;
|
||||
|
||||
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
|
||||
use Chill\MainBundle\Workflow\Helper\MetadataExtractor;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
|
||||
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
|
||||
use Symfony\Component\Workflow\Registry;
|
||||
use function array_key_exists;
|
||||
|
||||
class AccompanyingPeriodWorkEvaluationNormalizer implements ContextAwareNormalizerInterface, NormalizerAwareInterface
|
||||
{
|
||||
use NormalizerAwareTrait;
|
||||
|
||||
private const IGNORE_EVALUATION = 'evaluation:ignore';
|
||||
|
||||
private EntityWorkflowRepository $entityWorkflowRepository;
|
||||
|
||||
private MetadataExtractor $metadataExtractor;
|
||||
|
||||
private Registry $registry;
|
||||
|
||||
public function __construct(Registry $registry, EntityWorkflowRepository $entityWorkflowRepository, MetadataExtractor $metadataExtractor)
|
||||
{
|
||||
$this->registry = $registry;
|
||||
$this->entityWorkflowRepository = $entityWorkflowRepository;
|
||||
$this->metadataExtractor = $metadataExtractor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccompanyingPeriodWorkEvaluation $object
|
||||
*/
|
||||
public function normalize($object, ?string $format = null, array $context = []): array
|
||||
{
|
||||
$initial = $this->normalizer->normalize($object, $format, array_merge(
|
||||
$context,
|
||||
[self::IGNORE_EVALUATION => spl_object_hash($object)]
|
||||
));
|
||||
|
||||
// then, we add normalization for things which are not into the entity
|
||||
|
||||
$initial['workflows_availables'] = $this->metadataExtractor->availableWorkflowFor(
|
||||
AccompanyingPeriodWorkEvaluation::class,
|
||||
$object->getId()
|
||||
);
|
||||
|
||||
$workflows = $this->entityWorkflowRepository->findBy([
|
||||
'relatedEntityClass' => AccompanyingPeriodWorkEvaluation::class,
|
||||
'relatedEntityId' => $object->getId(),
|
||||
]);
|
||||
$initial['workflows'] = $this->normalizer->normalize($workflows, 'json', $context);
|
||||
|
||||
return $initial;
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, ?string $format = null, array $context = []): bool
|
||||
{
|
||||
return 'json' === $format
|
||||
&& $data instanceof AccompanyingPeriodWorkEvaluation
|
||||
&& !array_key_exists(self::IGNORE_EVALUATION, $context);
|
||||
}
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
<?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\Serializer\Normalizer;
|
||||
|
||||
use ArrayObject;
|
||||
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
|
||||
use Chill\MainBundle\Workflow\Helper\MetadataExtractor;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
|
||||
use Symfony\Component\Serializer\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
|
||||
use Symfony\Component\Workflow\Registry;
|
||||
use function array_key_exists;
|
||||
|
||||
class AccompanyingPeriodWorkNormalizer implements ContextAwareNormalizerInterface, NormalizerAwareInterface
|
||||
{
|
||||
use NormalizerAwareTrait;
|
||||
|
||||
private const IGNORE_WORK = 'ignore:work';
|
||||
|
||||
private EntityWorkflowRepository $entityWorkflowRepository;
|
||||
|
||||
private MetadataExtractor $metadataExtractor;
|
||||
|
||||
private Registry $registry;
|
||||
|
||||
public function __construct(Registry $registry, EntityWorkflowRepository $entityWorkflowRepository, MetadataExtractor $metadataExtractor)
|
||||
{
|
||||
$this->registry = $registry;
|
||||
$this->entityWorkflowRepository = $entityWorkflowRepository;
|
||||
$this->metadataExtractor = $metadataExtractor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccompanyingPeriodWork $object
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*
|
||||
* @return array|ArrayObject|bool|float|int|string|null
|
||||
*/
|
||||
public function normalize($object, ?string $format = null, array $context = [])
|
||||
{
|
||||
$initial = $this->normalizer->normalize($object, $format, array_merge(
|
||||
$context,
|
||||
[self::IGNORE_WORK => spl_object_hash($object)]
|
||||
));
|
||||
|
||||
// then, we add normalization for things which are not into the entity
|
||||
|
||||
$initial['workflows_availables'] = $this->metadataExtractor->availableWorkflowFor(
|
||||
AccompanyingPeriodWork::class,
|
||||
$object->getId()
|
||||
);
|
||||
|
||||
$initial['workflows_availables_evaluation'] = $this->metadataExtractor->availableWorkflowFor(
|
||||
AccompanyingPeriodWorkEvaluation::class
|
||||
);
|
||||
|
||||
$workflows = $this->entityWorkflowRepository->findBy([
|
||||
'relatedEntityClass' => AccompanyingPeriodWork::class,
|
||||
'relatedEntityId' => $object->getId(),
|
||||
]);
|
||||
$initial['workflows'] = $this->normalizer->normalize($workflows, 'json', $context);
|
||||
|
||||
return $initial;
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, ?string $format = null, array $context = []): bool
|
||||
{
|
||||
return 'json' === $format
|
||||
&& $data instanceof AccompanyingPeriodWork
|
||||
&& !array_key_exists(self::IGNORE_WORK, $context);
|
||||
}
|
||||
}
|
@@ -12,6 +12,8 @@ declare(strict_types=1);
|
||||
namespace Chill\PersonBundle\Serializer\Normalizer;
|
||||
|
||||
use Chill\PersonBundle\Entity\Household\Household;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdComposition;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdCompositionType;
|
||||
use Chill\PersonBundle\Entity\Household\Position;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Household\MembersEditor;
|
||||
@@ -22,6 +24,7 @@ use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
|
||||
|
||||
use UnexpectedValueException;
|
||||
use function array_key_exists;
|
||||
|
||||
class MembersEditorNormalizer implements DenormalizerAwareInterface, DenormalizerInterface
|
||||
@@ -148,6 +151,23 @@ class MembersEditorNormalizer implements DenormalizerAwareInterface, Denormalize
|
||||
);
|
||||
}
|
||||
|
||||
if (null !== $data['composition']) {
|
||||
$compositionType = $this->denormalizer->denormalize($data['composition']['household_composition_type'], HouseholdCompositionType::class, $format, $context);
|
||||
$numberOfChildren = $data['composition']['number_of_children'];
|
||||
$startDate = $this->denormalizer->denormalize($data['composition']['start_date'], DateTimeImmutable::class, $format, $context);
|
||||
|
||||
if (null === $compositionType) {
|
||||
throw new UnexpectedValueException('composition type cannot be null');
|
||||
}
|
||||
|
||||
$householdComposition = (new HouseholdComposition())
|
||||
->setHouseholdCompositionType($compositionType)
|
||||
->setNumberOfChildren($numberOfChildren)
|
||||
->setStartDate($startDate);
|
||||
|
||||
$household->addComposition($householdComposition);
|
||||
}
|
||||
|
||||
return $editor;
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,70 @@
|
||||
<?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\Serializer\Normalizer;
|
||||
|
||||
use ArrayObject;
|
||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
|
||||
use Chill\MainBundle\Workflow\Helper\MetadataExtractor;
|
||||
use Symfony\Component\Serializer\Exception\ExceptionInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
|
||||
use Symfony\Component\Workflow\Registry;
|
||||
use function array_key_exists;
|
||||
|
||||
class WorkflowNormalizer implements ContextAwareNormalizerInterface, NormalizerAwareInterface
|
||||
{
|
||||
use NormalizerAwareTrait;
|
||||
|
||||
private const IGNORE_ENTITY_WORKFLOW = 'ignore:entity_workflow';
|
||||
|
||||
private MetadataExtractor $metadataExtractor;
|
||||
|
||||
private Registry $registry;
|
||||
|
||||
public function __construct(Registry $registry, MetadataExtractor $metadataExtractor)
|
||||
{
|
||||
$this->registry = $registry;
|
||||
$this->metadataExtractor = $metadataExtractor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EntityWorkflow $object
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*
|
||||
* @return array|ArrayObject|bool|float|int|string|void|null
|
||||
*/
|
||||
public function normalize($object, ?string $format = null, array $context = []): array
|
||||
{
|
||||
$data = $this->normalizer->normalize($object, $format, array_merge(
|
||||
$context,
|
||||
[self::IGNORE_ENTITY_WORKFLOW => spl_object_hash($object)]
|
||||
));
|
||||
|
||||
$workflow = $this->registry->get($object, $object->getWorkflowName());
|
||||
|
||||
$data['workflow'] = $this->metadataExtractor->buildArrayPresentationForWorkflow($workflow);
|
||||
$data['current_place'] = $this->metadataExtractor->buildArrayPresentationForPlace($object);
|
||||
$data['current_place_at'] = $this->normalizer->normalize($object->getCurrentStepCreatedAt(), 'json', ['groups' => ['read']]);
|
||||
$data['current_place_by'] = $this->normalizer->normalize($object->getCurrentStepCreatedBy(), 'json', ['groups' => ['read']]);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, ?string $format = null, array $context = []): bool
|
||||
{
|
||||
return 'json' === $format
|
||||
&& $data instanceof EntityWorkflow
|
||||
&& !array_key_exists(self::IGNORE_ENTITY_WORKFLOW, $context);
|
||||
}
|
||||
}
|
@@ -169,6 +169,7 @@ final class HouseholdMemberControllerTest extends WebTestCase
|
||||
],
|
||||
],
|
||||
'destination' => null,
|
||||
'composition' => null,
|
||||
]
|
||||
)
|
||||
);
|
||||
@@ -223,6 +224,7 @@ final class HouseholdMemberControllerTest extends WebTestCase
|
||||
'type' => 'household',
|
||||
'id' => $householdId,
|
||||
],
|
||||
'composition' => null,
|
||||
]
|
||||
)
|
||||
);
|
||||
@@ -272,6 +274,7 @@ final class HouseholdMemberControllerTest extends WebTestCase
|
||||
'destination' => [
|
||||
'type' => 'household',
|
||||
],
|
||||
'composition' => null,
|
||||
]
|
||||
)
|
||||
);
|
||||
|
@@ -0,0 +1,47 @@
|
||||
<?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 Entity\Household;
|
||||
|
||||
use Chill\PersonBundle\Entity\Household\Household;
|
||||
use Chill\PersonBundle\Entity\Household\HouseholdComposition;
|
||||
use DateTimeImmutable;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
final class HouseholdTest extends TestCase
|
||||
{
|
||||
public function testHouseholdComposition()
|
||||
{
|
||||
$household = new Household();
|
||||
|
||||
$household->addComposition(($first = new HouseholdComposition())
|
||||
->setStartDate(new DateTimeImmutable('2021-12-01')));
|
||||
|
||||
$this->assertNull($first->getEndDate());
|
||||
|
||||
$household->addComposition(($second = new HouseholdComposition())
|
||||
->setStartDate(new DateTimeImmutable('2021-12-31')));
|
||||
|
||||
$this->assertEquals(new DateTimeImmutable('2021-12-31'), $first->getEndDate());
|
||||
$this->assertEquals(new DateTimeImmutable('2021-12-31'), $second->getStartDate());
|
||||
|
||||
$household->addComposition(($inside = new HouseholdComposition())
|
||||
->setStartDate(new DateTimeImmutable('2021-12-15')));
|
||||
|
||||
$this->assertEquals(new DateTimeImmutable('2021-12-15'), $first->getEndDate());
|
||||
$this->assertEquals(new DateTimeImmutable('2021-12-31'), $second->getStartDate());
|
||||
$this->assertEquals(new DateTimeImmutable('2021-12-31'), $inside->getEndDate());
|
||||
}
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
<?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\Workflow;
|
||||
|
||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
|
||||
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
|
||||
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationRepository;
|
||||
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkEvaluationVoter;
|
||||
|
||||
class AccompanyingPeriodWorkEvaluationWorkflowHandler implements EntityWorkflowHandlerInterface
|
||||
{
|
||||
private AccompanyingPeriodWorkEvaluationRepository $repository;
|
||||
|
||||
public function __construct(AccompanyingPeriodWorkEvaluationRepository $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
public function getRelatedEntity(EntityWorkflow $entityWorkflow): ?AccompanyingPeriodWorkEvaluation
|
||||
{
|
||||
return $this->repository->find($entityWorkflow->getRelatedEntityId());
|
||||
}
|
||||
|
||||
public function getRoleShow(EntityWorkflow $entityWorkflow): ?string
|
||||
{
|
||||
return AccompanyingPeriodWorkEvaluationVoter::SEE;
|
||||
}
|
||||
|
||||
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string
|
||||
{
|
||||
return '@ChillPerson/Workflow/_evaluation.html.twig';
|
||||
}
|
||||
|
||||
public function getTemplateData(EntityWorkflow $entityWorkflow, array $options = []): array
|
||||
{
|
||||
return [
|
||||
'entity_workflow' => $entityWorkflow,
|
||||
'evaluation' => $this->getRelatedEntity($entityWorkflow),
|
||||
];
|
||||
}
|
||||
|
||||
public function getTemplateTitle(EntityWorkflow $entityWorkflow, array $options = []): string
|
||||
{
|
||||
return '@ChillPerson/Workflow/_evaluation.title.html.twig';
|
||||
}
|
||||
|
||||
public function getTemplateTitleData(EntityWorkflow $entityWorkflow, array $options = []): array
|
||||
{
|
||||
return $this->getTemplateData($entityWorkflow, $options);
|
||||
}
|
||||
|
||||
public function supports(EntityWorkflow $entityWorkflow, array $options = []): bool
|
||||
{
|
||||
return $entityWorkflow->getRelatedEntityClass() === AccompanyingPeriodWorkEvaluation::class;
|
||||
}
|
||||
|
||||
public function supportsFreeze(EntityWorkflow $entityWorkflow, array $options = []): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
<?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\Workflow;
|
||||
|
||||
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
|
||||
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
|
||||
|
||||
class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHandlerInterface
|
||||
{
|
||||
private AccompanyingPeriodWorkRepository $repository;
|
||||
|
||||
public function __construct(AccompanyingPeriodWorkRepository $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
public function getRelatedEntity(EntityWorkflow $entityWorkflow): ?object
|
||||
{
|
||||
return $this->repository->find($entityWorkflow->getRelatedEntityId());
|
||||
}
|
||||
|
||||
public function getRoleShow(EntityWorkflow $entityWorkflow): ?string
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string
|
||||
{
|
||||
return '@ChillPerson/Workflow/_accompanying_period_work.html.twig';
|
||||
}
|
||||
|
||||
public function getTemplateData(EntityWorkflow $entityWorkflow, array $options = []): array
|
||||
{
|
||||
return [
|
||||
'entity_workflow' => $entityWorkflow,
|
||||
'work' => $this->getRelatedEntity($entityWorkflow),
|
||||
];
|
||||
}
|
||||
|
||||
public function getTemplateTitle(EntityWorkflow $entityWorkflow, array $options = []): string
|
||||
{
|
||||
return '@ChillPerson/Workflow/_accompanying_period_work.title.html.twig';
|
||||
}
|
||||
|
||||
public function getTemplateTitleData(EntityWorkflow $entityWorkflow, array $options = []): array
|
||||
{
|
||||
return $this->getTemplateData($entityWorkflow, $options);
|
||||
}
|
||||
|
||||
public function supports(EntityWorkflow $entityWorkflow, array $options = []): bool
|
||||
{
|
||||
return $entityWorkflow->getRelatedEntityClass() === AccompanyingPeriodWork::class;
|
||||
}
|
||||
|
||||
public function supportsFreeze(EntityWorkflow $entityWorkflow, array $options = []): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -93,3 +93,8 @@ services:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: '../Validator/Constraints/AccompanyingPeriod'
|
||||
|
||||
Chill\PersonBundle\Workflow\:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
resource: '../Workflow/'
|
||||
|
@@ -20,9 +20,19 @@ services:
|
||||
|
||||
Chill\PersonBundle\AccompanyingPeriod\Suggestion\ReferralsSuggestionInterface: '@Chill\PersonBundle\AccompanyingPeriod\Suggestion\ReferralsSuggestion'
|
||||
|
||||
Chill\PersonBundle\AccompanyingPeriod\Workflow\:
|
||||
resource: './../../AccompanyingPeriod/Workflow'
|
||||
Chill\PersonBundle\AccompanyingPeriod\Events\:
|
||||
resource: './../../AccompanyingPeriod/Events'
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\PersonBundle\AccompanyingPeriod\Events\UserRefEventSubscriber:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
tags:
|
||||
- # these are the options required to define the entity listener
|
||||
name: 'doctrine.orm.entity_listener'
|
||||
event: 'postUpdate'
|
||||
entity: 'Chill\PersonBundle\Entity\AccompanyingPeriod'
|
||||
|
||||
# set the 'lazy' option to TRUE to only instantiate listeners when they are used
|
||||
lazy: true
|
||||
|
@@ -25,3 +25,15 @@ services:
|
||||
autoconfigure: true
|
||||
tags:
|
||||
- { name: security.voter }
|
||||
|
||||
Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkEvaluationVoter:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Chill\PersonBundle\Security\Authorization\HouseholdVoter:
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
@@ -0,0 +1,51 @@
|
||||
<?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\Migrations\Person;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20220121121310 extends AbstractMigration
|
||||
{
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP SEQUENCE chill_person_household_composition_id_seq CASCADE');
|
||||
$this->addSql('DROP SEQUENCE chill_person_household_composition_type_id_seq CASCADE');
|
||||
$this->addSql('DROP TABLE chill_person_household_composition');
|
||||
$this->addSql('DROP TABLE chill_person_household_composition_type');
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Create table for household composition';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('CREATE SEQUENCE chill_person_household_composition_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||
$this->addSql('CREATE SEQUENCE chill_person_household_composition_type_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||
$this->addSql('CREATE TABLE chill_person_household_composition (id INT NOT NULL, household_id INT NOT NULL, endDate DATE DEFAULT NULL, numberOfChildren INT DEFAULT NULL, startDate DATE NOT NULL, createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, comment_comment TEXT DEFAULT NULL, comment_date TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL, comment_userId INT DEFAULT NULL, householdCompositionType_id INT NOT NULL, createdBy_id INT DEFAULT NULL, updatedBy_id INT DEFAULT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('CREATE INDEX IDX_E62BEE83E79FF843 ON chill_person_household_composition (household_id)');
|
||||
$this->addSql('CREATE INDEX IDX_E62BEE83CDEA4FCF ON chill_person_household_composition (householdCompositionType_id)');
|
||||
$this->addSql('CREATE INDEX IDX_E62BEE833174800F ON chill_person_household_composition (createdBy_id)');
|
||||
$this->addSql('CREATE INDEX IDX_E62BEE8365FF1AEC ON chill_person_household_composition (updatedBy_id)');
|
||||
$this->addSql('COMMENT ON COLUMN chill_person_household_composition.endDate IS \'(DC2Type:date_immutable)\'');
|
||||
$this->addSql('COMMENT ON COLUMN chill_person_household_composition.startDate IS \'(DC2Type:date_immutable)\'');
|
||||
$this->addSql('CREATE TABLE chill_person_household_composition_type (id INT NOT NULL, active BOOLEAN NOT NULL, label JSON NOT NULL, PRIMARY KEY(id))');
|
||||
$this->addSql('ALTER TABLE chill_person_household_composition ADD CONSTRAINT FK_E62BEE83E79FF843 FOREIGN KEY (household_id) REFERENCES chill_person_household (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE chill_person_household_composition ADD CONSTRAINT FK_E62BEE83CDEA4FCF FOREIGN KEY (householdCompositionType_id) REFERENCES chill_person_household_composition_type (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE chill_person_household_composition ADD CONSTRAINT FK_E62BEE833174800F FOREIGN KEY (createdBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('ALTER TABLE chill_person_household_composition ADD CONSTRAINT FK_E62BEE8365FF1AEC FOREIGN KEY (updatedBy_id) REFERENCES users (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||
$this->addSql('COMMENT ON COLUMN chill_person_household_composition.createdAt IS \'(DC2Type:date_immutable)\'');
|
||||
$this->addSql('COMMENT ON COLUMN chill_person_household_composition.updatedAt IS \'(DC2Type:date_immutable)\'');
|
||||
}
|
||||
}
|
@@ -98,3 +98,17 @@ household:
|
||||
from: Depuis
|
||||
to: Jusqu'au
|
||||
person history: Ménages
|
||||
|
||||
household_composition:
|
||||
Since: >-
|
||||
Depuis le {startDate, date, long}
|
||||
Still active: Toujours actif
|
||||
Until: >-
|
||||
Jusqu'au {endDate, date, long}
|
||||
numberOfChildren children in household: >-
|
||||
{numberOfChildren, plural,
|
||||
=0 {Aucun enfant dans le ménage}
|
||||
one {1 enfant dans le ménage}
|
||||
few {# enfants dans le ménage}
|
||||
other {# enfants dans le ménage}
|
||||
}
|
||||
|
@@ -498,3 +498,14 @@ period_notification:
|
||||
You are getting a notification for a period which does not exists any more: Cette notification ne correspond pas à une période d'accompagnement valide.
|
||||
You are getting a notification for a period you are not allowed to see: La notification fait référence à une période d'accompagnement à laquelle vous n'avez pas accès.
|
||||
This is the minimal period details: Période d'accompagnement n°
|
||||
|
||||
household_composition:
|
||||
No composition yet: Aucune composition familiale renseignée
|
||||
Compositions: Composition familiale
|
||||
endDate: Date de fin
|
||||
numberOfChildren: Nombre d'enfants mineurs au sein du ménage
|
||||
Household composition: Composition du ménage
|
||||
Composition added: Information sur la composition familiale ajoutée
|
||||
Currently no composition: Aucune composition famiale renseignée.
|
||||
Add a composition: Ajouter une composition familiale
|
||||
Update composition: Modifier la composition familiale
|
||||
|
Reference in New Issue
Block a user