mirror of
				https://gitlab.com/Chill-Projet/chill-bundles.git
				synced 2025-11-04 03:08:25 +00:00 
			
		
		
		
	Compare commits
	
		
			95 Commits
		
	
	
		
			43-wopi-us
			...
			693-filter
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						25cbb528ec
	
				 | 
					
					
						|||
| 
						
						
							
						
						2d013e110a
	
				 | 
					
					
						|||
| 
						
						
							
						
						9e63480c70
	
				 | 
					
					
						|||
| 988495df27 | |||
| cc62c9cc4a | |||
| 40924d9d39 | |||
| 8b505410ca | |||
| d535ec6cfb | |||
| 9029426d03 | |||
| 9ae2e51819 | |||
| 68f7a832b4 | |||
| af5f27ff49 | |||
| 5e58d36e79 | |||
| 
						
						
							
						
						b0ab591cbd
	
				 | 
					
					
						|||
| 
						
						
							
						
						d8af7d455e
	
				 | 
					
					
						|||
| 
						
						
							
						
						5830c3e177
	
				 | 
					
					
						|||
| 
						
						
							
						
						88eefa698b
	
				 | 
					
					
						|||
| c64ec89274 | |||
| 16ec858ee8 | |||
| 
						
						
							
						
						de55ff920f
	
				 | 
					
					
						|||
| 
						
						
							
						
						885256ac0d
	
				 | 
					
					
						|||
| f53d3852c3 | |||
| 9f5b11e6cc | |||
| e5bc74d11d | |||
| 5c0d89a88b | |||
| 56a17a0bcd | |||
| 9ffe1ff8a8 | |||
| c790b22496 | |||
| e54c2ca712 | |||
| 2f091a639b | |||
| 9ada19ef23 | |||
| 8ee184e665 | |||
| c5f842076f | |||
| f9b151e4db | |||
| 
						
						
							
						
						2c360e979b
	
				 | 
					
					
						|||
| 
						
						
							
						
						459df26fef
	
				 | 
					
					
						|||
| 
						
						
							
						
						e36d2a5eec
	
				 | 
					
					
						|||
| 
						
						
							
						
						0301641290
	
				 | 
					
					
						|||
| 
						
						
							
						
						5c413edb32
	
				 | 
					
					
						|||
| 8e3a83de85 | |||
| 050a4feab5 | |||
| 
						
						
							
						
						06238c8355
	
				 | 
					
					
						|||
| 
						
						
							
						
						6b90a7d2a7
	
				 | 
					
					
						|||
| de5f818c5a | |||
| c4eb45edcc | |||
| 
						
						
							
						
						99482edf0d
	
				 | 
					
					
						|||
| 
						
						
							
						
						e87f0bf348
	
				 | 
					
					
						|||
| 
						
						
							
						
						bd324753f3
	
				 | 
					
					
						|||
| 
						
						
							
						
						7915aae86f
	
				 | 
					
					
						|||
| 
						
						
							
						
						4fec18f3aa
	
				 | 
					
					
						|||
| 
						
						
							
						
						583d7b24ba
	
				 | 
					
					
						|||
| 
						
						
							
						
						4a56c4c945
	
				 | 
					
					
						|||
| 
						
						
							
						
						239a978adb
	
				 | 
					
					
						|||
| 
						
						
							
						
						b2dec3e587
	
				 | 
					
					
						|||
| 
						
						
							
						
						6bba6f68b3
	
				 | 
					
					
						|||
| 
						
						
							
						
						164beb3ca9
	
				 | 
					
					
						|||
| 
						
						
							
						
						25dd65fbd8
	
				 | 
					
					
						|||
| 
						
						
							
						
						e99fb75ebd
	
				 | 
					
					
						|||
| 
						
						
							
						
						08ddbee6af
	
				 | 
					
					
						|||
| 
						
						
							
						
						a2b2cafbce
	
				 | 
					
					
						|||
| 
						
						
							
						
						a913d2820d
	
				 | 
					
					
						|||
| 
						
						
							
						
						01790fa0cf
	
				 | 
					
					
						|||
| 
						
						
							
						
						582983f5ef
	
				 | 
					
					
						|||
| 
						
						
							
						
						1f48900434
	
				 | 
					
					
						|||
| 
						
						
							
						
						91494c07d5
	
				 | 
					
					
						|||
| 
						
						
							
						
						c05d153029
	
				 | 
					
					
						|||
| 
						
						
							
						
						5fea61c450
	
				 | 
					
					
						|||
| 
						
						
							
						
						e7ac8aafe1
	
				 | 
					
					
						|||
| 
						
						
							
						
						99455ca685
	
				 | 
					
					
						|||
| 2deed644b6 | |||
| 5211d092e3 | |||
| ac084a1309 | |||
| 2ca3cced2e | |||
| f17c08f530 | |||
| 2a9ebe436e | |||
| 6ab5e708ec | |||
| 7abecdea02 | |||
| 2be8aefb38 | |||
| ff930e94f6 | |||
| 38ff46f03f | |||
| 9f00754eb7 | |||
| 0f7d4ce5ee | |||
| 1eb1e2ec24 | |||
| 52512e45fc | |||
| 49380f5f61 | |||
| ff7f5a5dd3 | |||
| fb8f74119f | |||
| 34602d0a56 | |||
| 43a4576ed4 | |||
| a32d20e320 | |||
| 7e6ef3dafe | |||
| 7e06d7beed | |||
| 8e65b3851a | |||
| 5a93e21758 | |||
| 368846e09b | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -3,6 +3,7 @@ composer
 | 
			
		||||
composer.phar
 | 
			
		||||
composer.lock
 | 
			
		||||
docs/build/
 | 
			
		||||
node_modules/*
 | 
			
		||||
.php_cs.cache
 | 
			
		||||
 | 
			
		||||
###> symfony/framework-bundle ###
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,6 @@
 | 
			
		||||
        "symfony/translation": "^4.4",
 | 
			
		||||
        "symfony/twig-bundle": "^4.4",
 | 
			
		||||
        "symfony/validator": "^4.4",
 | 
			
		||||
        "symfony/web-link": "*",
 | 
			
		||||
        "symfony/webpack-encore-bundle": "^1.11",
 | 
			
		||||
        "symfony/workflow": "^4.4",
 | 
			
		||||
        "symfony/yaml": "^4.4",
 | 
			
		||||
 
 | 
			
		||||
@@ -43,6 +43,7 @@ use Symfony\Component\HttpFoundation\Request;
 | 
			
		||||
use Symfony\Component\HttpFoundation\Response;
 | 
			
		||||
use Symfony\Component\Security\Core\Role\Role;
 | 
			
		||||
use Symfony\Component\Serializer\SerializerInterface;
 | 
			
		||||
use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
use function array_key_exists;
 | 
			
		||||
 | 
			
		||||
final class ActivityController extends AbstractController
 | 
			
		||||
@@ -73,6 +74,8 @@ final class ActivityController extends AbstractController
 | 
			
		||||
 | 
			
		||||
    private ThirdPartyRepository $thirdPartyRepository;
 | 
			
		||||
 | 
			
		||||
    private TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    private UserRepositoryInterface $userRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
@@ -89,7 +92,8 @@ final class ActivityController extends AbstractController
 | 
			
		||||
        LoggerInterface $logger,
 | 
			
		||||
        SerializerInterface $serializer,
 | 
			
		||||
        UserRepositoryInterface $userRepository,
 | 
			
		||||
        CenterResolverManagerInterface $centerResolver
 | 
			
		||||
        CenterResolverManagerInterface $centerResolver,
 | 
			
		||||
        TranslatorInterface $translator
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->activityACLAwareRepository = $activityACLAwareRepository;
 | 
			
		||||
        $this->activityTypeRepository = $activityTypeRepository;
 | 
			
		||||
@@ -105,6 +109,7 @@ final class ActivityController extends AbstractController
 | 
			
		||||
        $this->serializer = $serializer;
 | 
			
		||||
        $this->userRepository = $userRepository;
 | 
			
		||||
        $this->centerResolver = $centerResolver;
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -160,7 +165,7 @@ final class ActivityController extends AbstractController
 | 
			
		||||
                $this->entityManager->remove($activity);
 | 
			
		||||
                $this->entityManager->flush();
 | 
			
		||||
 | 
			
		||||
                $this->addFlash('success', $this->get('translator')
 | 
			
		||||
                $this->addFlash('success', $this->translator
 | 
			
		||||
                    ->trans('The activity has been successfully removed.'));
 | 
			
		||||
 | 
			
		||||
                $params = $this->buildParamsToUrl($person, $accompanyingPeriod);
 | 
			
		||||
@@ -245,7 +250,7 @@ final class ActivityController extends AbstractController
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $this->addFlash('success', $this->get('translator')->trans('Success : activity updated!'));
 | 
			
		||||
            $this->addFlash('success', $this->translator->trans('Success : activity updated!'));
 | 
			
		||||
 | 
			
		||||
            return $this->redirectToRoute('chill_activity_activity_show', $params);
 | 
			
		||||
        }
 | 
			
		||||
@@ -473,7 +478,7 @@ final class ActivityController extends AbstractController
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $this->addFlash('success', $this->get('translator')->trans('Success : activity created!'));
 | 
			
		||||
            $this->addFlash('success', $this->translator->trans('Success : activity created!'));
 | 
			
		||||
 | 
			
		||||
            $params = $this->buildParamsToUrl($person, $accompanyingPeriod);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,15 +13,24 @@ namespace Chill\ActivityBundle\Controller;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Entity\ActivityReason;
 | 
			
		||||
use Chill\ActivityBundle\Form\ActivityReasonType;
 | 
			
		||||
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
 | 
			
		||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
 | 
			
		||||
use Symfony\Component\HttpFoundation\Request;
 | 
			
		||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * ActivityReason controller.
 | 
			
		||||
 */
 | 
			
		||||
class ActivityReasonController extends AbstractController
 | 
			
		||||
{
 | 
			
		||||
    private ActivityReasonRepository $activityReasonRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(ActivityReasonRepository $activityReasonRepository)
 | 
			
		||||
    {
 | 
			
		||||
        $this->activityReasonRepository = $activityReasonRepository;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a new ActivityReason entity.
 | 
			
		||||
     */
 | 
			
		||||
@@ -56,8 +65,8 @@ class ActivityReasonController extends AbstractController
 | 
			
		||||
 | 
			
		||||
        $entity = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReason::class)->find($id);
 | 
			
		||||
 | 
			
		||||
        if (!$entity) {
 | 
			
		||||
            throw $this->createNotFoundException('Unable to find ActivityReason entity.');
 | 
			
		||||
        if (null === $entity) {
 | 
			
		||||
            throw new NotFoundHttpException('Unable to find ActivityReason entity.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $editForm = $this->createEditForm($entity);
 | 
			
		||||
@@ -75,7 +84,7 @@ class ActivityReasonController extends AbstractController
 | 
			
		||||
    {
 | 
			
		||||
        $em = $this->getDoctrine()->getManager();
 | 
			
		||||
 | 
			
		||||
        $entities = $em->getRepository(\Chill\ActivityBundle\Entity\ActivityReason::class)->findAll();
 | 
			
		||||
        $entities = $this->activityReasonRepository->findAll();
 | 
			
		||||
 | 
			
		||||
        return $this->render('ChillActivityBundle:ActivityReason:index.html.twig', [
 | 
			
		||||
            'entities' => $entities,
 | 
			
		||||
 
 | 
			
		||||
@@ -63,10 +63,8 @@ class ActivityReason
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get category.
 | 
			
		||||
     *
 | 
			
		||||
     * @return ActivityReasonCategory
 | 
			
		||||
     */
 | 
			
		||||
    public function getCategory()
 | 
			
		||||
    public function getCategory(): ?ActivityReasonCategory
 | 
			
		||||
    {
 | 
			
		||||
        return $this->category;
 | 
			
		||||
    }
 | 
			
		||||
@@ -107,6 +105,11 @@ class ActivityReason
 | 
			
		||||
        return $this->name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function isActiveAndParentActive(): bool
 | 
			
		||||
    {
 | 
			
		||||
        return $this->active && null !== $this->getCategory() && $this->getCategory()->getActive();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set active.
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -60,7 +60,7 @@ class ByCreatorAggregator implements AggregatorInterface
 | 
			
		||||
                return 'Created by';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value) {
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ class BySocialActionAggregator implements AggregatorInterface
 | 
			
		||||
                return 'Social action';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value) {
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ class BySocialIssueAggregator implements AggregatorInterface
 | 
			
		||||
                return 'Social issues';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value) {
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ class ByThirdpartyAggregator implements AggregatorInterface
 | 
			
		||||
                return 'Accepted thirdparty';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value) {
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ class CreatorScopeAggregator implements AggregatorInterface
 | 
			
		||||
                return 'Scope';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value) {
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,11 +65,13 @@ class LocationTypeAggregator implements AggregatorInterface
 | 
			
		||||
                return 'Accepted locationtype';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value) {
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $lt = $this->locationTypeRepository->find($value);
 | 
			
		||||
            if (null === $lt = $this->locationTypeRepository->find($value)) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return $this->translatableStringHelper->localize(
 | 
			
		||||
                $lt->getTitle()
 | 
			
		||||
 
 | 
			
		||||
@@ -71,7 +71,7 @@ class ActivityTypeAggregator implements AggregatorInterface
 | 
			
		||||
                return 'Activity type';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value) {
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ class ActivityUserAggregator implements AggregatorInterface
 | 
			
		||||
                return 'Activity user';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value) {
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ class ActivityUsersAggregator implements AggregatorInterface
 | 
			
		||||
                return 'Activity users';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value) {
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,7 @@ class ActivityUsersJobAggregator implements \Chill\MainBundle\Export\AggregatorI
 | 
			
		||||
                return 'Users \'s job';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value) {
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,7 @@ class ActivityUsersScopeAggregator implements \Chill\MainBundle\Export\Aggregato
 | 
			
		||||
                return 'Users \'s scope';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value) {
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -134,6 +134,10 @@ class ActivityReasonAggregator implements AggregatorInterface, ExportElementVali
 | 
			
		||||
                return 'reasons' === $data['level'] ? 'Group by reasons' : 'Group by categories of reason';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            switch ($data['level']) {
 | 
			
		||||
                case 'reasons':
 | 
			
		||||
                    $r = $this->activityReasonRepository->find($value);
 | 
			
		||||
 
 | 
			
		||||
@@ -57,6 +57,7 @@ class SentReceivedAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
            switch ($value) {
 | 
			
		||||
                case null:
 | 
			
		||||
                case '':
 | 
			
		||||
                    return '';
 | 
			
		||||
 | 
			
		||||
                case 'sent':
 | 
			
		||||
 
 | 
			
		||||
@@ -17,11 +17,9 @@ use Chill\ActivityBundle\Repository\ActivityTypeRepositoryInterface;
 | 
			
		||||
use Chill\MainBundle\Export\FilterInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Chill\PersonBundle\Export\Declarations;
 | 
			
		||||
use Doctrine\ORM\Query\Expr;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class ActivityTypeFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
@@ -44,14 +42,13 @@ class ActivityTypeFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('activity', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->join(Activity::class, 'activity', Expr\Join::WITH, 'activity.accompanyingPeriod = acp');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $clause = $qb->expr()->in('activity.activityType', ':selected_activity_types');
 | 
			
		||||
 | 
			
		||||
        $qb->andWhere($clause);
 | 
			
		||||
        $qb->setParameter('selected_activity_types', $data['types']);
 | 
			
		||||
        $qb->andWhere(
 | 
			
		||||
            $qb->expr()->exists(
 | 
			
		||||
                'SELECT 1 FROM ' . Activity::class . ' act_type_filter_activity
 | 
			
		||||
                WHERE act_type_filter_activity.activityType IN (:act_type_filter_activity_types) AND act_type_filter_activity.accompanyingPeriod = acp'
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
        $qb->setParameter('act_type_filter_activity_types', $data['accepted_activitytypes']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn()
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,74 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\ActivityBundle\Export\Filter\ACPFilters;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Export\FilterInterface;
 | 
			
		||||
use Chill\MainBundle\Form\Type\PickUserLocationType;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class LocationFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    private TranslatableStringHelper $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TranslatableStringHelper $translatableStringHelper)
 | 
			
		||||
    {
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        $qb->andWhere(
 | 
			
		||||
            $qb->expr()->in('activity.location', ':location')
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        $qb->setParameter('location', $data['accepted_location']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn(): string
 | 
			
		||||
    {
 | 
			
		||||
        return Declarations::ACTIVITY_ACP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        $builder->add('accepted_location', PickUserLocationType::class, [
 | 
			
		||||
            'multiple' => true,
 | 
			
		||||
            'label' => 'pick location'
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function describeAction($data, $format = 'string'): array
 | 
			
		||||
    {
 | 
			
		||||
        $locations = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($data['accepted_location'] as $location) {
 | 
			
		||||
            $locations[] = $location->getName();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ['Filtered activity by location: only %locations%', [
 | 
			
		||||
            '%locations%' => implode(', ', $locations),
 | 
			
		||||
        ]];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'Filter activity by location';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -50,7 +50,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
 | 
			
		||||
    {
 | 
			
		||||
        $where = $qb->getDQLPart('where');
 | 
			
		||||
        $join = $qb->getDQLPart('join');
 | 
			
		||||
        $clause = $qb->expr()->in('reasons', ':selected_activity_reasons');
 | 
			
		||||
        $clause = $qb->expr()->in('actreasons', ':selected_activity_reasons');
 | 
			
		||||
 | 
			
		||||
        if (!in_array('actreasons', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->join('activity.reasons', 'actreasons');
 | 
			
		||||
@@ -77,6 +77,7 @@ class ActivityReasonFilter implements ExportElementValidatedInterface, FilterInt
 | 
			
		||||
            'class' => ActivityReason::class,
 | 
			
		||||
            'choice_label' => fn (ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getName()),
 | 
			
		||||
            'group_by' => fn (ActivityReason $reason) => $this->translatableStringHelper->localize($reason->getCategory()->getName()),
 | 
			
		||||
            'attr' => ['class' => 'select2 '],
 | 
			
		||||
            'multiple' => true,
 | 
			
		||||
            'expanded' => false,
 | 
			
		||||
        ]);
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,8 @@ declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Chill\ActivityBundle\Form;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategory;
 | 
			
		||||
use Chill\ActivityBundle\Entity\ActivityReason;
 | 
			
		||||
use Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategoryType;
 | 
			
		||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
 | 
			
		||||
use Symfony\Component\Form\AbstractType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
 | 
			
		||||
@@ -25,13 +26,13 @@ class ActivityReasonType extends AbstractType
 | 
			
		||||
        $builder
 | 
			
		||||
            ->add('name', TranslatableStringFormType::class)
 | 
			
		||||
            ->add('active', CheckboxType::class, ['required' => false])
 | 
			
		||||
            ->add('category', TranslatableActivityReasonCategory::class);
 | 
			
		||||
            ->add('category', TranslatableActivityReasonCategoryType::class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function configureOptions(OptionsResolver $resolver)
 | 
			
		||||
    {
 | 
			
		||||
        $resolver->setDefaults([
 | 
			
		||||
            'data_class' => 'Chill\ActivityBundle\Entity\ActivityReason',
 | 
			
		||||
            'data_class' => ActivityReason::class,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ namespace Chill\ActivityBundle\Form;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Entity\Activity;
 | 
			
		||||
use Chill\ActivityBundle\Entity\ActivityPresence;
 | 
			
		||||
use Chill\ActivityBundle\Entity\ActivityReason;
 | 
			
		||||
use Chill\ActivityBundle\Form\Type\PickActivityReasonType;
 | 
			
		||||
use Chill\ActivityBundle\Security\Authorization\ActivityVoter;
 | 
			
		||||
use Chill\DocStoreBundle\Form\StoredObjectType;
 | 
			
		||||
use Chill\MainBundle\Entity\Center;
 | 
			
		||||
@@ -229,19 +229,10 @@ class ActivityType extends AbstractType
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($activityType->isVisible('reasons')) {
 | 
			
		||||
            $builder->add('reasons', EntityType::class, [
 | 
			
		||||
            $builder->add('reasons', PickActivityReasonType::class, [
 | 
			
		||||
                'label' => $activityType->getLabel('reasons'),
 | 
			
		||||
                'required' => $activityType->isRequired('reasons'),
 | 
			
		||||
                'class' => ActivityReason::class,
 | 
			
		||||
                'multiple' => true,
 | 
			
		||||
                'choice_label' => function (ActivityReason $activityReason) {
 | 
			
		||||
                    return $this->translatableStringHelper->localize($activityReason->getName());
 | 
			
		||||
                },
 | 
			
		||||
                'attr' => ['class' => 'select2 '],
 | 
			
		||||
                'query_builder' => static function (EntityRepository $er) {
 | 
			
		||||
                    return $er->createQueryBuilder('a')
 | 
			
		||||
                        ->where('a.active = true');
 | 
			
		||||
                },
 | 
			
		||||
            ]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,9 +12,9 @@ declare(strict_types=1);
 | 
			
		||||
namespace Chill\ActivityBundle\Form\Type;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Entity\ActivityReason;
 | 
			
		||||
use Chill\ActivityBundle\Repository\ActivityReasonRepository;
 | 
			
		||||
use Chill\ActivityBundle\Templating\Entity\ActivityReasonRender;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Doctrine\ORM\EntityRepository;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\AbstractType;
 | 
			
		||||
use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
			
		||||
@@ -22,31 +22,29 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
			
		||||
/**
 | 
			
		||||
 * FormType to choose amongst activity reasons.
 | 
			
		||||
 */
 | 
			
		||||
class TranslatableActivityReason extends AbstractType
 | 
			
		||||
class PickActivityReasonType extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var ActivityReasonRender
 | 
			
		||||
     */
 | 
			
		||||
    protected $reasonRender;
 | 
			
		||||
    private ActivityReasonRepository $activityReasonRepository;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var TranslatableStringHelper
 | 
			
		||||
     */
 | 
			
		||||
    protected $translatableStringHelper;
 | 
			
		||||
    private ActivityReasonRender $reasonRender;
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        TranslatableStringHelper $translatableStringHelper,
 | 
			
		||||
        ActivityReasonRender $reasonRender
 | 
			
		||||
        ActivityReasonRepository $activityReasonRepository,
 | 
			
		||||
        ActivityReasonRender $reasonRender,
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
        $this->activityReasonRepository = $activityReasonRepository;
 | 
			
		||||
        $this->reasonRender = $reasonRender;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function configureOptions(OptionsResolver $resolver)
 | 
			
		||||
    {
 | 
			
		||||
        $resolver->setDefaults(
 | 
			
		||||
            [
 | 
			
		||||
                'class' => 'ChillActivityBundle:ActivityReason',
 | 
			
		||||
                'class' => ActivityReason::class,
 | 
			
		||||
                'choice_label' => function (ActivityReason $choice) {
 | 
			
		||||
                    return $this->reasonRender->renderString($choice, []);
 | 
			
		||||
                },
 | 
			
		||||
@@ -57,10 +55,7 @@ class TranslatableActivityReason extends AbstractType
 | 
			
		||||
 | 
			
		||||
                    return null;
 | 
			
		||||
                },
 | 
			
		||||
                'query_builder' => static function (EntityRepository $er) {
 | 
			
		||||
                    return $er->createQueryBuilder('r')
 | 
			
		||||
                        ->where('r.active = true');
 | 
			
		||||
                },
 | 
			
		||||
                'choices' => $this->activityReasonRepository->findAll(),
 | 
			
		||||
                'attr' => ['class' => ' select2 '],
 | 
			
		||||
            ]
 | 
			
		||||
        );
 | 
			
		||||
@@ -1,59 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\ActivityBundle\Form\Type;
 | 
			
		||||
 | 
			
		||||
use Doctrine\ORM\EntityRepository;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\AbstractType;
 | 
			
		||||
use Symfony\Component\HttpFoundation\RequestStack;
 | 
			
		||||
use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Description of TranslatableActivityReasonCategory.
 | 
			
		||||
 */
 | 
			
		||||
class TranslatableActivityReasonCategory extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var RequestStack
 | 
			
		||||
     */
 | 
			
		||||
    private $requestStack;
 | 
			
		||||
 | 
			
		||||
    public function __construct(RequestStack $requestStack)
 | 
			
		||||
    {
 | 
			
		||||
        $this->requestStack = $requestStack;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function configureOptions(OptionsResolver $resolver)
 | 
			
		||||
    {
 | 
			
		||||
        $locale = $this->requestStack->getCurrentRequest()->getLocale();
 | 
			
		||||
        $resolver->setDefaults(
 | 
			
		||||
            [
 | 
			
		||||
                'class' => 'ChillActivityBundle:ActivityReasonCategory',
 | 
			
		||||
                'choice_label' => 'name[' . $locale . ']',
 | 
			
		||||
                'query_builder' => static function (EntityRepository $er) {
 | 
			
		||||
                    return $er->createQueryBuilder('c')
 | 
			
		||||
                        ->where('c.active = true');
 | 
			
		||||
                },
 | 
			
		||||
            ]
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getBlockPrefix()
 | 
			
		||||
    {
 | 
			
		||||
        return 'translatable_activity_reason_category';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getParent()
 | 
			
		||||
    {
 | 
			
		||||
        return EntityType::class;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,58 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\ActivityBundle\Form\Type;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Entity\ActivityReasonCategory;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\AbstractType;
 | 
			
		||||
use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
			
		||||
use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Description of TranslatableActivityReasonCategory.
 | 
			
		||||
 */
 | 
			
		||||
class TranslatableActivityReasonCategoryType extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    private TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TranslatableStringHelperInterface $translatableStringHelper, TranslatorInterface $translator)
 | 
			
		||||
    {
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function configureOptions(OptionsResolver $resolver)
 | 
			
		||||
    {
 | 
			
		||||
        $resolver->setDefaults(
 | 
			
		||||
            [
 | 
			
		||||
                'class' => ActivityReasonCategory::class,
 | 
			
		||||
                'choice_label' => function (ActivityReasonCategory $category) {
 | 
			
		||||
                    return $this->translatableStringHelper->localize($category->getName())
 | 
			
		||||
                        . (!$category->getActive() ? ' (' . $this->translator->trans('inactive') . ')' : '');
 | 
			
		||||
                },
 | 
			
		||||
            ]
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getBlockPrefix()
 | 
			
		||||
    {
 | 
			
		||||
        return 'translatable_activity_reason_category';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getParent()
 | 
			
		||||
    {
 | 
			
		||||
        return EntityType::class;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -36,7 +36,6 @@ final class AdminMenuBuilder implements LocalMenuBuilderInterface
 | 
			
		||||
            ->setAttribute('class', 'list-group-item-header')
 | 
			
		||||
            ->setExtras([
 | 
			
		||||
                'order' => 5000,
 | 
			
		||||
                'icons' => ['exchange'],
 | 
			
		||||
            ]);
 | 
			
		||||
 | 
			
		||||
        $menu->addChild('Activity Reasons', [
 | 
			
		||||
 
 | 
			
		||||
@@ -14,17 +14,38 @@ namespace Chill\ActivityBundle\Repository;
 | 
			
		||||
use Chill\ActivityBundle\Entity\ActivityReason;
 | 
			
		||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
 | 
			
		||||
use Doctrine\Persistence\ManagerRegistry;
 | 
			
		||||
use Symfony\Component\HttpFoundation\RequestStack;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @method ActivityReason|null find($id, $lockMode = null, $lockVersion = null)
 | 
			
		||||
 * @method ActivityReason|null findOneBy(array $criteria, array $orderBy = null)
 | 
			
		||||
 * @method ActivityReason[]    findAll()
 | 
			
		||||
 * @method ActivityReason[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 | 
			
		||||
 */
 | 
			
		||||
class ActivityReasonRepository extends ServiceEntityRepository
 | 
			
		||||
{
 | 
			
		||||
    public function __construct(ManagerRegistry $registry)
 | 
			
		||||
    {
 | 
			
		||||
    private RequestStack $requestStack;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ManagerRegistry $registry,
 | 
			
		||||
        RequestStack $requestStack
 | 
			
		||||
    ) {
 | 
			
		||||
        parent::__construct($registry, ActivityReason::class);
 | 
			
		||||
 | 
			
		||||
        $this->requestStack = $requestStack;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return ActivityReason[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findAll(): array
 | 
			
		||||
    {
 | 
			
		||||
        $qb = $this->createQueryBuilder('ar');
 | 
			
		||||
        $qb->select(['ar'])
 | 
			
		||||
            ->leftJoin('ar.category', 'category')
 | 
			
		||||
            ->addOrderBy('JSON_EXTRACT(category.name, :lang)')
 | 
			
		||||
            ->addOrderBy('JSON_EXTRACT(ar.name, :lang)')
 | 
			
		||||
            ->setParameter('lang', $this->requestStack->getCurrentRequest()->getLocale() ?? 'fr');
 | 
			
		||||
 | 
			
		||||
        return $qb->getQuery()->getResult();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -156,7 +156,7 @@
 | 
			
		||||
                <dd>
 | 
			
		||||
                    <section class="chill-entity entity-comment-embeddable">
 | 
			
		||||
                        <blockquote class="chill-user-quote private-quote">
 | 
			
		||||
                            {{ entity.privateComment.comments[userId] }}
 | 
			
		||||
                            {{ entity.privateComment.comments[userId]|chill_markdown_to_html }}
 | 
			
		||||
                        </blockquote>
 | 
			
		||||
                    </section>
 | 
			
		||||
                </dd>
 | 
			
		||||
@@ -168,11 +168,11 @@
 | 
			
		||||
                    {% if entity.documents|length > 0 %}
 | 
			
		||||
                        <ul>
 | 
			
		||||
                            {% for d in entity.documents %}
 | 
			
		||||
                                <li>{{ d.title }}{{ m.download_button(d) }}</li>
 | 
			
		||||
                                <li>{{ d.title }} {{ d|chill_document_button_group() }}</li>
 | 
			
		||||
                            {% endfor %}
 | 
			
		||||
                        </ul>
 | 
			
		||||
                    {% else %}
 | 
			
		||||
                        <span class="chill-no-data-statement">{{ 'Any document found'|trans }}</span>
 | 
			
		||||
                        <span class="chill-no-data-statement">{{ 'No document found'|trans }}</span>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                </dd>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,12 +8,14 @@
 | 
			
		||||
    {{ parent() }}
 | 
			
		||||
    {{ encore_entry_script_tags('mod_notification_toggle_read_status') }}
 | 
			
		||||
    {{ encore_entry_script_tags('mod_async_upload') }}
 | 
			
		||||
    {{ encore_entry_script_tags('mod_document_action_buttons_group') }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block css %}
 | 
			
		||||
    {{ parent() }}
 | 
			
		||||
    {{ encore_entry_link_tags('mod_notification_toggle_read_status') }}
 | 
			
		||||
    {{ encore_entry_link_tags('mod_async_upload') }}
 | 
			
		||||
    {{ encore_entry_link_tags('mod_document_action_buttons_group') }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,13 +7,13 @@
 | 
			
		||||
{% block js %}
 | 
			
		||||
    {{ parent() }}
 | 
			
		||||
    {{ encore_entry_script_tags('mod_notification_toggle_read_status') }}
 | 
			
		||||
    {{ encore_entry_link_tags('mod_async_upload') }}
 | 
			
		||||
    {{ encore_entry_script_tags('mod_document_action_buttons_group') }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block css %}
 | 
			
		||||
    {{ parent() }}
 | 
			
		||||
    {{ encore_entry_link_tags('mod_notification_toggle_read_status') }}
 | 
			
		||||
    {{ encore_entry_link_tags('mod_async_upload') }}
 | 
			
		||||
    {{ encore_entry_link_tags('mod_document_action_buttons_group') }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% import 'ChillActivityBundle:ActivityReason:macro.html.twig' as m %}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,22 +7,34 @@
 | 
			
		||||
        <thead>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <th>{{ 'Name'|trans }}</th>
 | 
			
		||||
                <th>{{ 'Active'|trans }}</th>
 | 
			
		||||
                <th>{{ 'Actions'|trans }}</th>
 | 
			
		||||
            </tr>
 | 
			
		||||
        </thead>
 | 
			
		||||
        <tbody>
 | 
			
		||||
        {% for entity in entities %}
 | 
			
		||||
            <tr class="{% if entity.active %}active{% else %}inactive{% endif %}">
 | 
			
		||||
                <td><a href="{{ path('chill_activity_activityreason_show', { 'id': entity.id }) }}">{{ entity.name|localize_translatable_string }}</a></td>
 | 
			
		||||
                <td>
 | 
			
		||||
                <ul class="record_actions">
 | 
			
		||||
                    <li>
 | 
			
		||||
                        <a href="{{ path('chill_activity_activityreason_show', { 'id': entity.id }) }}" class="btn btn-show" title="{{ 'show'|trans }}"></a>
 | 
			
		||||
                    </li>
 | 
			
		||||
                    <li>
 | 
			
		||||
                        <a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
 | 
			
		||||
                    </li>
 | 
			
		||||
                </ul>
 | 
			
		||||
                    {% if entity.category is not null -%}
 | 
			
		||||
                    {{  entity.category.name|localize_translatable_string }} >
 | 
			
		||||
                    {% endif -%}
 | 
			
		||||
                    {{ entity.name|localize_translatable_string }}
 | 
			
		||||
                </td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <i class="fa {% if entity.active %}fa-check-square-o{% else %}fa-square-o{% endif %}"></i>
 | 
			
		||||
                    {% if entity.active and not entity.isActiveAndParentActive %}
 | 
			
		||||
                    <span class="badge text-bg-danger text-white">{{ 'Associated activity reason category is inactive'|trans }}</span>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                </td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <ul class="record_actions">
 | 
			
		||||
                        <li>
 | 
			
		||||
                            <a href="{{ path('chill_activity_activityreason_show', { 'id': entity.id }) }}" class="btn btn-show" title="{{ 'show'|trans }}"></a>
 | 
			
		||||
                        </li>
 | 
			
		||||
                        <li>
 | 
			
		||||
                            <a href="{{ path('chill_activity_activityreason_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
 | 
			
		||||
                        </li>
 | 
			
		||||
                    </ul>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
        <thead>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <th>{{ 'Name'|trans }}</th>
 | 
			
		||||
                <th>{{ 'Active'|trans }}</th>
 | 
			
		||||
                <th>{{ 'Actions'|trans }}</th>
 | 
			
		||||
            </tr>
 | 
			
		||||
        </thead>
 | 
			
		||||
@@ -14,7 +15,11 @@
 | 
			
		||||
        {% for entity in entities %}
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <a href="{{ path('chill_activity_activityreasoncategory_show', { 'id': entity.id }) }}">{{ entity.name|localize_translatable_string }}</a></td>
 | 
			
		||||
                    {{ entity.name|localize_translatable_string }}
 | 
			
		||||
                </td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <i class="fa {% if entity.active %}fa-check-square-o{% else %}fa-square-o{% endif %}"></i>
 | 
			
		||||
                </td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <ul class="record_actions">
 | 
			
		||||
                    <li>
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Chill\ActivityBundle\Tests\Form\Type;
 | 
			
		||||
 | 
			
		||||
use Chill\ActivityBundle\Form\Type\TranslatableActivityReason;
 | 
			
		||||
use Chill\ActivityBundle\Form\Type\PickActivityReasonType;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Symfony\Component\Form\PreloadedExtension;
 | 
			
		||||
use Symfony\Component\Form\Test\TypeTestCase;
 | 
			
		||||
@@ -36,7 +36,7 @@ final class TranslatableActivityReasonTest extends TypeTestCase
 | 
			
		||||
 | 
			
		||||
    public function testSimple()
 | 
			
		||||
    {
 | 
			
		||||
        $translatableActivityReasonType = new TranslatableActivityReason(
 | 
			
		||||
        $translatableActivityReasonType = new PickActivityReasonType(
 | 
			
		||||
            $this->getTranslatableStringHelper()
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,11 @@
 | 
			
		||||
services:
 | 
			
		||||
    Chill\ActivityBundle\Controller\ActivityController:
 | 
			
		||||
    _defaults:
 | 
			
		||||
        autowire: true
 | 
			
		||||
        autoconfigure: true
 | 
			
		||||
 | 
			
		||||
    Chill\ActivityBundle\Controller\:
 | 
			
		||||
        resource: '../../Controller/'
 | 
			
		||||
        tags: ['controller.service_arguments']
 | 
			
		||||
 | 
			
		||||
    Chill\ActivityBundle\Controller\ActivityController:
 | 
			
		||||
        tags: ['controller.service_arguments']
 | 
			
		||||
 
 | 
			
		||||
@@ -79,6 +79,11 @@ services:
 | 
			
		||||
        tags:
 | 
			
		||||
            - { name: chill.export_filter, alias: 'accompanyingcourse_activitytype_filter' }
 | 
			
		||||
 | 
			
		||||
    chill.activity.export.location_filter:
 | 
			
		||||
        class: Chill\ActivityBundle\Export\Filter\ACPFilters\LocationFilter
 | 
			
		||||
        tags:
 | 
			
		||||
            - { name: chill.export_filter, alias: 'activity_location_filter' }
 | 
			
		||||
 | 
			
		||||
    chill.activity.export.locationtype_filter:
 | 
			
		||||
        class: Chill\ActivityBundle\Export\Filter\ACPFilters\LocationTypeFilter
 | 
			
		||||
        tags:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,12 @@
 | 
			
		||||
---
 | 
			
		||||
services:
 | 
			
		||||
    chill.activity.form.type.translatableactivityreasoncategory:
 | 
			
		||||
        class: Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategory
 | 
			
		||||
        arguments:
 | 
			
		||||
            - "@request_stack"
 | 
			
		||||
        tags:
 | 
			
		||||
            - { name: form.type, alias: translatable_activity_reason_category }
 | 
			
		||||
    Chill\ActivityBundle\Form\Type\TranslatableActivityReasonCategoryType:
 | 
			
		||||
        autowire: true
 | 
			
		||||
        autoconfigure: true
 | 
			
		||||
 | 
			
		||||
    chill.activity.form.type.translatableactivityreason:
 | 
			
		||||
        class: Chill\ActivityBundle\Form\Type\TranslatableActivityReason
 | 
			
		||||
        arguments:
 | 
			
		||||
            $translatableStringHelper: "@chill.main.helper.translatable_string"
 | 
			
		||||
            $reasonRender: '@Chill\ActivityBundle\Templating\Entity\ActivityReasonRender'
 | 
			
		||||
        tags:
 | 
			
		||||
            - { name: form.type, alias: translatable_activity_reason }
 | 
			
		||||
    Chill\ActivityBundle\Form\Type\PickActivityReasonType:
 | 
			
		||||
        autowire: true
 | 
			
		||||
        autoconfigure: true
 | 
			
		||||
 | 
			
		||||
    chill.activity.form.type.translatableactivitytype:
 | 
			
		||||
        class: Chill\ActivityBundle\Form\Type\TranslatableActivityType
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,8 @@
 | 
			
		||||
---
 | 
			
		||||
services:
 | 
			
		||||
    Chill\ActivityBundle\Repository\ActivityReasonRepository:
 | 
			
		||||
        autowire: true
 | 
			
		||||
 | 
			
		||||
    chill_activity.repository.activity_type: '@Chill\ActivityBundle\Repository\ActivityTypeRepository'
 | 
			
		||||
    chill_activity.repository.reason: '@Chill\ActivityBundle\Repository\ActivityReasonRepository'
 | 
			
		||||
    chill_activity.repository.reason_category: '@Chill\ActivityBundle\Repository\ActivityReasonCategoryRepository'
 | 
			
		||||
 
 | 
			
		||||
@@ -117,6 +117,7 @@ Activity Reasons: Sujets d'une activité
 | 
			
		||||
Activity Reasons Category: Catégories de sujet d'activités
 | 
			
		||||
Activity Types Categories: Catégories des types d'activité
 | 
			
		||||
Activity Presences: Presences aux activités
 | 
			
		||||
Associated activity reason category is inactive: La catégorie de sujet attachée est inactive
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Crud
 | 
			
		||||
@@ -251,6 +252,8 @@ Activity reasons for those activities: Sujets de ces activités
 | 
			
		||||
 | 
			
		||||
Filter by activity type: Filtrer les activités par type
 | 
			
		||||
 | 
			
		||||
Filter activity by location: Filtrer les activités par localisation
 | 
			
		||||
'Filtered activity by location: only %locations%': "Filtré par localisation: uniquement %locations%"
 | 
			
		||||
Filter activity by locationtype: Filtrer les activités par type de localisation
 | 
			
		||||
'Filtered activity by locationtype: only %types%': "Filtré par type de localisation: uniquement %types%"
 | 
			
		||||
Accepted locationtype: Types de localisation
 | 
			
		||||
@@ -276,7 +279,7 @@ Creators: Créateurs
 | 
			
		||||
Filter activity by userscope: Filtrer les activités par service du créateur
 | 
			
		||||
'Filtered activity by userscope: only %scopes%': "Filtré par service du créateur: uniquement %scopes%"
 | 
			
		||||
Accepted userscope: Services
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
Filter acp which has no activity: Filtrer les parcours qui n’ont pas d’activité
 | 
			
		||||
Filtered acp which has no activities: Filtrer les parcours sans activité associée
 | 
			
		||||
Group acp by activity number: Grouper les parcours par nombre d’activité
 | 
			
		||||
 
 | 
			
		||||
@@ -53,19 +53,15 @@ class ByActivityTypeAggregator implements AggregatorInterface
 | 
			
		||||
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        $this->asideActivityCategoryRepository->findBy(['id' => $values]);
 | 
			
		||||
 | 
			
		||||
        return function ($value): string {
 | 
			
		||||
            if ('_header' === $value) {
 | 
			
		||||
                return 'export.aggregator.Aside activity type';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value) {
 | 
			
		||||
            if (null === $value || null === $t = $this->asideActivityCategoryRepository->find($value)) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $t = $this->asideActivityCategoryRepository->find($value);
 | 
			
		||||
 | 
			
		||||
            return $this->translatableStringHelper->localize($t->getTitle());
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,89 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\AsideActivityBundle\Export\Aggregator;
 | 
			
		||||
 | 
			
		||||
use Chill\AsideActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Export\AggregatorInterface;
 | 
			
		||||
use Chill\MainBundle\Repository\UserJobRepositoryInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class ByUserJobAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    private UserJobRepositoryInterface $userJobRepository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(UserJobRepositoryInterface $userJobRepository, TranslatableStringHelperInterface $translatableStringHelper)
 | 
			
		||||
    {
 | 
			
		||||
        $this->userJobRepository = $userJobRepository;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('aside_user', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->leftJoin('aside.agent', 'aside_user');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $qb
 | 
			
		||||
            ->addSelect('IDENTITY(aside_user.userJob) AS aside_activity_user_job_aggregator')
 | 
			
		||||
            ->addGroupBy('aside_activity_user_job_aggregator');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn()
 | 
			
		||||
    {
 | 
			
		||||
        return Declarations::ASIDE_ACTIVITY_TYPE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        // nothing to add in the form
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        return function ($value): string {
 | 
			
		||||
            if ('_header' === $value) {
 | 
			
		||||
                return 'Users \'s job';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $j = $this->userJobRepository->find($value);
 | 
			
		||||
 | 
			
		||||
            return $this->translatableStringHelper->localize(
 | 
			
		||||
                $j->getLabel()
 | 
			
		||||
            );
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getQueryKeys($data): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['aside_activity_user_job_aggregator'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle()
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.aggregator.Aggregate by user job';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,89 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\AsideActivityBundle\Export\Aggregator;
 | 
			
		||||
 | 
			
		||||
use Chill\AsideActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Export\AggregatorInterface;
 | 
			
		||||
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
use function in_array;
 | 
			
		||||
 | 
			
		||||
class ByUserScopeAggregator implements AggregatorInterface
 | 
			
		||||
{
 | 
			
		||||
    private ScopeRepositoryInterface $scopeRepository;
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(ScopeRepositoryInterface $scopeRepository, TranslatableStringHelperInterface $translatableStringHelper)
 | 
			
		||||
    {
 | 
			
		||||
        $this->scopeRepository = $scopeRepository;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if (!in_array('aside_user', $qb->getAllAliases(), true)) {
 | 
			
		||||
            $qb->leftJoin('aside.agent', 'aside_user');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $qb
 | 
			
		||||
            ->addSelect('IDENTITY(aside_user.mainScope) AS aside_activity_user_scope_aggregator')
 | 
			
		||||
            ->addGroupBy('aside_activity_user_scope_aggregator');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn()
 | 
			
		||||
    {
 | 
			
		||||
        return Declarations::ASIDE_ACTIVITY_TYPE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        // nothing to add in the form
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        return function ($value): string {
 | 
			
		||||
            if ('_header' === $value) {
 | 
			
		||||
                return 'Users \'s scope';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (null === $value || '' === $value) {
 | 
			
		||||
                return '';
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $s = $this->scopeRepository->find($value);
 | 
			
		||||
 | 
			
		||||
            return $this->translatableStringHelper->localize(
 | 
			
		||||
                $s->getName()
 | 
			
		||||
            );
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getQueryKeys($data): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['aside_activity_user_scope_aggregator'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle()
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.aggregator.Aggregate by user scope';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,102 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\AsideActivityBundle\Export\Export;
 | 
			
		||||
 | 
			
		||||
use Chill\AsideActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\AsideActivityBundle\Repository\AsideActivityRepository;
 | 
			
		||||
use Chill\AsideActivityBundle\Security\AsideActivityVoter;
 | 
			
		||||
use Chill\MainBundle\Export\ExportInterface;
 | 
			
		||||
use Chill\MainBundle\Export\FormatterInterface;
 | 
			
		||||
use Chill\MainBundle\Export\GroupedExportInterface;
 | 
			
		||||
use Doctrine\ORM\Query;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class AvgAsideActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
{
 | 
			
		||||
    private AsideActivityRepository $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        AsideActivityRepository $repository
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->repository = $repository;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getAllowedFormattersTypes(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [FormatterInterface::TYPE_TABULAR];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getDescription(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.Average aside activities duration';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getGroup(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.Exports of aside activities';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if ('export_avg_aside_activity_duration' !== $key) {
 | 
			
		||||
            throw new LogicException("the key {$key} is not used by this export");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return static fn ($value) => '_header' === $value ? 'Average duration aside activities' : $value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getQueryKeys($data): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['export_avg_aside_activity_duration'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getResult($query, $data)
 | 
			
		||||
    {
 | 
			
		||||
        return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.Average aside activities duration';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getType(): string
 | 
			
		||||
    {
 | 
			
		||||
        return Declarations::ASIDE_ACTIVITY_TYPE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
 | 
			
		||||
    {
 | 
			
		||||
        $qb = $this->repository->createQueryBuilder('aside');
 | 
			
		||||
 | 
			
		||||
        $qb
 | 
			
		||||
            ->select('AVG(aside.duration) as export_avg_aside_activity_duration')
 | 
			
		||||
            ->andWhere($qb->expr()->isNotNull('aside.duration'));
 | 
			
		||||
 | 
			
		||||
        return $qb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function requiredRole(): string
 | 
			
		||||
    {
 | 
			
		||||
        return AsideActivityVoter::STATS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function supportsModifiers(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [Declarations::ASIDE_ACTIVITY_TYPE];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -11,12 +11,12 @@ declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Chill\AsideActivityBundle\Export\Export;
 | 
			
		||||
 | 
			
		||||
use Chill\AsideActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\AsideActivityBundle\Repository\AsideActivityRepository;
 | 
			
		||||
use Chill\AsideActivityBundle\Security\AsideActivityVoter;
 | 
			
		||||
use Chill\MainBundle\Export\ExportInterface;
 | 
			
		||||
use Chill\MainBundle\Export\FormatterInterface;
 | 
			
		||||
use Chill\MainBundle\Export\GroupedExportInterface;
 | 
			
		||||
use ChillAsideActivityBundle\Export\Declarations;
 | 
			
		||||
use Doctrine\ORM\Query;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
@@ -100,6 +100,8 @@ class CountAsideActivity implements ExportInterface, GroupedExportInterface
 | 
			
		||||
 | 
			
		||||
    public function supportsModifiers(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [];
 | 
			
		||||
        return [
 | 
			
		||||
            Declarations::ASIDE_ACTIVITY_TYPE,
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,236 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace Chill\AsideActivityBundle\Export\Export;
 | 
			
		||||
 | 
			
		||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
 | 
			
		||||
use Chill\AsideActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\AsideActivityBundle\Form\AsideActivityCategoryType;
 | 
			
		||||
use Chill\AsideActivityBundle\Repository\AsideActivityCategoryRepository;
 | 
			
		||||
use Chill\AsideActivityBundle\Security\AsideActivityVoter;
 | 
			
		||||
use Chill\AsideActivityBundle\Templating\Entity\CategoryRender;
 | 
			
		||||
use Chill\MainBundle\Entity\Center;
 | 
			
		||||
use Chill\MainBundle\Export\FormatterInterface;
 | 
			
		||||
use Chill\MainBundle\Export\GroupedExportInterface;
 | 
			
		||||
use Chill\MainBundle\Export\Helper\DateTimeHelper;
 | 
			
		||||
use Chill\MainBundle\Export\Helper\UserHelper;
 | 
			
		||||
use Chill\MainBundle\Export\ListInterface;
 | 
			
		||||
use Chill\MainBundle\Repository\CenterRepositoryInterface;
 | 
			
		||||
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Closure;
 | 
			
		||||
use Doctrine\ORM\AbstractQuery;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
final class ListAsideActivity implements ListInterface, GroupedExportInterface
 | 
			
		||||
{
 | 
			
		||||
    private EntityManagerInterface $em;
 | 
			
		||||
 | 
			
		||||
    private UserHelper $userHelper;
 | 
			
		||||
 | 
			
		||||
    private DateTimeHelper $dateTimeHelper;
 | 
			
		||||
 | 
			
		||||
    private ScopeRepositoryInterface $scopeRepository;
 | 
			
		||||
 | 
			
		||||
    private CenterRepositoryInterface $centerRepository;
 | 
			
		||||
 | 
			
		||||
    private AsideActivityCategoryRepository $asideActivityCategoryRepository;
 | 
			
		||||
 | 
			
		||||
    private CategoryRender $categoryRender;
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        EntityManagerInterface $em,
 | 
			
		||||
        DateTimeHelper $dateTimeHelper,
 | 
			
		||||
        UserHelper $userHelper,
 | 
			
		||||
        ScopeRepositoryInterface $scopeRepository,
 | 
			
		||||
        CenterRepositoryInterface $centerRepository,
 | 
			
		||||
        AsideActivityCategoryRepository $asideActivityCategoryRepository,
 | 
			
		||||
        CategoryRender $categoryRender,
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->em = $em;
 | 
			
		||||
        $this->dateTimeHelper = $dateTimeHelper;
 | 
			
		||||
        $this->userHelper = $userHelper;
 | 
			
		||||
        $this->scopeRepository = $scopeRepository;
 | 
			
		||||
        $this->centerRepository = $centerRepository;
 | 
			
		||||
        $this->asideActivityCategoryRepository = $asideActivityCategoryRepository;
 | 
			
		||||
        $this->categoryRender = $categoryRender;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getAllowedFormattersTypes()
 | 
			
		||||
    {
 | 
			
		||||
        return [FormatterInterface::TYPE_LIST];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getDescription()
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.aside_activity.List of aside activities';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle()
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.aside_activity.List of aside activities';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getGroup(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.Exports of aside activities';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        switch ($key) {
 | 
			
		||||
            case 'id':
 | 
			
		||||
            case 'note':
 | 
			
		||||
                return function ($value) use ($key) {
 | 
			
		||||
                    if ('_header' === $value) {
 | 
			
		||||
                        return 'export.aside_activity.' . $key;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return $value ?? '';
 | 
			
		||||
                };
 | 
			
		||||
            case 'duration':
 | 
			
		||||
                return function ($value) use ($key) {
 | 
			
		||||
                    if ('_header' === $value) {
 | 
			
		||||
                        return 'export.aside_activity.' . $key;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (null === $value) {
 | 
			
		||||
                        return '';
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if ($value instanceof \DateTimeInterface) {
 | 
			
		||||
                        return $value->format('H:i:s');
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return $value;
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
            case 'createdAt':
 | 
			
		||||
            case 'updatedAt':
 | 
			
		||||
            case 'date':
 | 
			
		||||
                return $this->dateTimeHelper->getLabel('export.aside_activity.'.$key);
 | 
			
		||||
 | 
			
		||||
            case 'agent_id':
 | 
			
		||||
            case 'creator_id':
 | 
			
		||||
                return $this->userHelper->getLabel($key, $values, 'export.aside_activity.' . $key);
 | 
			
		||||
 | 
			
		||||
            case 'aside_activity_type':
 | 
			
		||||
                return function ($value) {
 | 
			
		||||
                    if ('_header' === $value) {
 | 
			
		||||
                        return 'export.aside_activity.aside_activity_type';
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (null === $value || '' === $value || null === $c = $this->asideActivityCategoryRepository->find($value)) {
 | 
			
		||||
                        return '';
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return $this->categoryRender->renderString($c, []);
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
            case 'main_scope':
 | 
			
		||||
                return function ($value) {
 | 
			
		||||
                    if ('_header' === $value) {
 | 
			
		||||
                        return 'export.aside_activity.main_scope';
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (null === $value || '' === $value || null === $c = $this->scopeRepository->find($value)) {
 | 
			
		||||
                        return '';
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return $this->translatableStringHelper->localize($c->getName());
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
            case 'main_center':
 | 
			
		||||
                return function ($value) {
 | 
			
		||||
                    if ('_header' === $value) {
 | 
			
		||||
                        return 'export.aside_activity.main_center';
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    /** @var Center $c */
 | 
			
		||||
                    if (null === $value || '' === $value || null === $c = $this->centerRepository->find($value)) {
 | 
			
		||||
                        return '';
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    return $c->getName();
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
                throw new \LogicException('this key is not supported : ' . $key);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getQueryKeys($data)
 | 
			
		||||
    {
 | 
			
		||||
        return [
 | 
			
		||||
            'id',
 | 
			
		||||
            'createdAt',
 | 
			
		||||
            'updatedAt',
 | 
			
		||||
            'agent_id',
 | 
			
		||||
            'creator_id',
 | 
			
		||||
            'main_scope',
 | 
			
		||||
            'main_center',
 | 
			
		||||
            'aside_activity_type',
 | 
			
		||||
            'date',
 | 
			
		||||
            'duration',
 | 
			
		||||
            'note'
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param QueryBuilder $query
 | 
			
		||||
     * @param array $data
 | 
			
		||||
     */
 | 
			
		||||
    public function getResult($query, $data): array
 | 
			
		||||
    {
 | 
			
		||||
        return $query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getType(): string
 | 
			
		||||
    {
 | 
			
		||||
        return Declarations::ASIDE_ACTIVITY_TYPE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
 | 
			
		||||
    {
 | 
			
		||||
        $qb = $this->em->createQueryBuilder()
 | 
			
		||||
            ->from(AsideActivity::class, 'aside')
 | 
			
		||||
            ->leftJoin('aside.agent', 'agent')
 | 
			
		||||
        ;
 | 
			
		||||
 | 
			
		||||
        $qb
 | 
			
		||||
            ->addSelect('aside.id AS id')
 | 
			
		||||
            ->addSelect('aside.createdAt AS createdAt')
 | 
			
		||||
            ->addSelect('aside.updatedAt AS updatedAt')
 | 
			
		||||
            ->addSelect('IDENTITY(aside.agent) AS agent_id')
 | 
			
		||||
            ->addSelect('IDENTITY(aside.createdBy) AS creator_id')
 | 
			
		||||
            ->addSelect('IDENTITY(agent.mainScope) AS main_scope')
 | 
			
		||||
            ->addSelect('IDENTITY(agent.mainCenter) AS main_center')
 | 
			
		||||
            ->addSelect('IDENTITY(aside.type) AS aside_activity_type')
 | 
			
		||||
            ->addSelect('aside.date')
 | 
			
		||||
            ->addSelect('aside.duration')
 | 
			
		||||
            ->addSelect('aside.note')
 | 
			
		||||
        ;
 | 
			
		||||
 | 
			
		||||
        return $qb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function requiredRole(): string
 | 
			
		||||
    {
 | 
			
		||||
        return AsideActivityVoter::STATS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function supportsModifiers()
 | 
			
		||||
    {
 | 
			
		||||
        return [Declarations::ASIDE_ACTIVITY_TYPE];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,102 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\AsideActivityBundle\Export\Export;
 | 
			
		||||
 | 
			
		||||
use Chill\AsideActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\AsideActivityBundle\Repository\AsideActivityRepository;
 | 
			
		||||
use Chill\AsideActivityBundle\Security\AsideActivityVoter;
 | 
			
		||||
use Chill\MainBundle\Export\ExportInterface;
 | 
			
		||||
use Chill\MainBundle\Export\FormatterInterface;
 | 
			
		||||
use Chill\MainBundle\Export\GroupedExportInterface;
 | 
			
		||||
use Doctrine\ORM\Query;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class SumAsideActivityDuration implements ExportInterface, GroupedExportInterface
 | 
			
		||||
{
 | 
			
		||||
    private AsideActivityRepository $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        AsideActivityRepository $repository
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->repository = $repository;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getAllowedFormattersTypes(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [FormatterInterface::TYPE_TABULAR];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getDescription(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.Sum aside activities duration';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getGroup(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.Exports of aside activities';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getLabels($key, array $values, $data)
 | 
			
		||||
    {
 | 
			
		||||
        if ('export_sum_aside_activity_duration' !== $key) {
 | 
			
		||||
            throw new LogicException("the key {$key} is not used by this export");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return static fn ($value) => '_header' === $value ? 'Sum duration aside activities' : $value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getQueryKeys($data): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['export_sum_aside_activity_duration'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getResult($query, $data)
 | 
			
		||||
    {
 | 
			
		||||
        return $query->getQuery()->getResult(Query::HYDRATE_SCALAR);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.Sum aside activities duration';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getType(): string
 | 
			
		||||
    {
 | 
			
		||||
        return Declarations::ASIDE_ACTIVITY_TYPE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function initiateQuery(array $requiredModifiers, array $acl, array $data = [])
 | 
			
		||||
    {
 | 
			
		||||
        $qb = $this->repository
 | 
			
		||||
            ->createQueryBuilder('aside');
 | 
			
		||||
 | 
			
		||||
        $qb->select('SUM(aside.duration) as export_sum_aside_activity_duration')
 | 
			
		||||
            ->andWhere($qb->expr()->isNotNull('aside.duration'));
 | 
			
		||||
 | 
			
		||||
        return $qb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function requiredRole(): string
 | 
			
		||||
    {
 | 
			
		||||
        return AsideActivityVoter::STATS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function supportsModifiers(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [Declarations::ASIDE_ACTIVITY_TYPE];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -80,8 +80,8 @@ class ByActivityTypeFilter implements FilterInterface
 | 
			
		||||
    public function describeAction($data, $format = 'string'): array
 | 
			
		||||
    {
 | 
			
		||||
        $types = array_map(
 | 
			
		||||
            fn (AsideActivityCategory $t): string => $this->translatableStringHelper->localize($t->getName()),
 | 
			
		||||
            $this->asideActivityTypeRepository->findBy(['id' => $data['types']->toArray()])
 | 
			
		||||
            fn (AsideActivityCategory $t): string => $this->translatableStringHelper->localize($t->getTitle()),
 | 
			
		||||
            $data['types']->toArray()
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return ['export.filter.Filtered by aside activity type: only %type%', [
 | 
			
		||||
 
 | 
			
		||||
@@ -46,25 +46,18 @@ class ByDateFilter implements FilterInterface
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        $where = $qb->getDQLPart('where');
 | 
			
		||||
        $clause = $qb->expr()->between(
 | 
			
		||||
            'aside.date',
 | 
			
		||||
            ':date_from',
 | 
			
		||||
            ':date_to'
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if ($where instanceof Andx) {
 | 
			
		||||
            $where->add($clause);
 | 
			
		||||
        } else {
 | 
			
		||||
            $where = $qb->expr()->andX($clause);
 | 
			
		||||
        }
 | 
			
		||||
        $qb->andWhere($clause);
 | 
			
		||||
 | 
			
		||||
        $qb->add('where', $where);
 | 
			
		||||
        $qb->setParameter(
 | 
			
		||||
            'date_from',
 | 
			
		||||
            $this->rollingDateConverter->convert($data['date_from'])
 | 
			
		||||
        );
 | 
			
		||||
        $qb->setParameter(
 | 
			
		||||
        )->setParameter(
 | 
			
		||||
            'date_to',
 | 
			
		||||
            $this->rollingDateConverter->convert($data['date_to'])
 | 
			
		||||
        );
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,75 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\AsideActivityBundle\Export\Filter;
 | 
			
		||||
 | 
			
		||||
use Chill\AsideActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Export\FilterInterface;
 | 
			
		||||
use Chill\MainBundle\Form\Type\PickUserDynamicType;
 | 
			
		||||
use Chill\MainBundle\Templating\Entity\UserRender;
 | 
			
		||||
use Doctrine\ORM\Query\Expr\Andx;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class ByUserFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    private UserRender $userRender;
 | 
			
		||||
 | 
			
		||||
    public function __construct(UserRender $userRender)
 | 
			
		||||
    {
 | 
			
		||||
        $this->userRender = $userRender;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        $clause = $qb->expr()->in('aside.agent', ':users');
 | 
			
		||||
 | 
			
		||||
        $qb
 | 
			
		||||
            ->andWhere($clause)
 | 
			
		||||
            ->setParameter('users', $data['accepted_users']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn(): string
 | 
			
		||||
    {
 | 
			
		||||
        return Declarations::ASIDE_ACTIVITY_TYPE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        $builder->add('accepted_users', PickUserDynamicType::class, [
 | 
			
		||||
            'multiple' => true,
 | 
			
		||||
            'label' => 'Creators',
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function describeAction($data, $format = 'string'): array
 | 
			
		||||
    {
 | 
			
		||||
        $users = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($data['accepted_users'] as $u) {
 | 
			
		||||
            $users[] = $this->userRender->renderString($u, []);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return ['export.filter.Filtered aside activity by user: only %users%', [
 | 
			
		||||
            '%users%' => implode(', ', $users),
 | 
			
		||||
        ]];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle(): string
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.filter.Filter aside activity by user';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,81 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\AsideActivityBundle\Export\Filter;
 | 
			
		||||
 | 
			
		||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
 | 
			
		||||
use Chill\AsideActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Entity\UserJob;
 | 
			
		||||
use Chill\MainBundle\Export\FilterInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class ByUserJobFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TranslatableStringHelperInterface $translatableStringHelper)
 | 
			
		||||
    {
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        $qb
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->exists(
 | 
			
		||||
                    'SELECT 1 FROM ' . AsideActivity::class . ' aside_activity_user_job_filter_act
 | 
			
		||||
                JOIN aside_activity_user_job_filter_act.agent aside_activity_user_job_filter_user WHERE aside_activity_user_job_filter_user.userJob IN (:aside_activity_user_job_filter_jobs) AND aside_activity_user_job_filter_act = aside'
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->setParameter('aside_activity_user_job_filter_jobs', $data['jobs']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn()
 | 
			
		||||
    {
 | 
			
		||||
        return Declarations::ASIDE_ACTIVITY_TYPE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        $builder->add('jobs', EntityType::class, [
 | 
			
		||||
            'class' => UserJob::class,
 | 
			
		||||
            'choice_label' => fn (UserJob $j) => $this->translatableStringHelper->localize($j->getLabel()),
 | 
			
		||||
            'multiple' => true,
 | 
			
		||||
            'expanded' => true,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function describeAction($data, $format = 'string')
 | 
			
		||||
    {
 | 
			
		||||
        return ['export.filter.Filtered aside activities by user jobs: only %jobs%', [
 | 
			
		||||
            '%jobs%' => implode(
 | 
			
		||||
                ', ',
 | 
			
		||||
                array_map(
 | 
			
		||||
                    fn (UserJob $job) => $this->translatableStringHelper->localize($job->getLabel()),
 | 
			
		||||
                    $data['jobs']->toArray()
 | 
			
		||||
                )
 | 
			
		||||
            ),
 | 
			
		||||
        ]];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle()
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.filter.Filter by user jobs';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,88 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\AsideActivityBundle\Export\Filter;
 | 
			
		||||
 | 
			
		||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
 | 
			
		||||
use Chill\AsideActivityBundle\Export\Declarations;
 | 
			
		||||
use Chill\MainBundle\Entity\Scope;
 | 
			
		||||
use Chill\MainBundle\Export\FilterInterface;
 | 
			
		||||
use Chill\MainBundle\Repository\ScopeRepositoryInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
 | 
			
		||||
class ByUserScopeFilter implements FilterInterface
 | 
			
		||||
{
 | 
			
		||||
    private ScopeRepositoryInterface $scopeRepository;
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ScopeRepositoryInterface $scopeRepository,
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->scopeRepository = $scopeRepository;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function addRole(): ?string
 | 
			
		||||
    {
 | 
			
		||||
        return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function alterQuery(QueryBuilder $qb, $data)
 | 
			
		||||
    {
 | 
			
		||||
        $qb
 | 
			
		||||
            ->andWhere(
 | 
			
		||||
                $qb->expr()->exists(
 | 
			
		||||
                    'SELECT 1 FROM ' . AsideActivity::class . ' aside_activity_user_scope_filter_act
 | 
			
		||||
                JOIN aside_activity_user_scope_filter_act.agent aside_activity_user_scope_filter_user WHERE aside_activity_user_scope_filter_user.mainScope IN (:aside_activity_user_scope_filter_scopes) AND  aside_activity_user_scope_filter_act = aside '
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
            ->setParameter('aside_activity_user_scope_filter_scopes', $data['scopes']);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function applyOn()
 | 
			
		||||
    {
 | 
			
		||||
        return Declarations::ASIDE_ACTIVITY_TYPE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder)
 | 
			
		||||
    {
 | 
			
		||||
        $builder->add('scopes', EntityType::class, [
 | 
			
		||||
            'class' => Scope::class,
 | 
			
		||||
            'choices' => $this->scopeRepository->findAllActive(),
 | 
			
		||||
            'choice_label' => fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
 | 
			
		||||
            'multiple' => true,
 | 
			
		||||
            'expanded' => true,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function describeAction($data, $format = 'string')
 | 
			
		||||
    {
 | 
			
		||||
        return ['export.filter.Filtered aside activities by user scope: only %scopes%', [
 | 
			
		||||
            '%scopes%' => implode(
 | 
			
		||||
                ', ',
 | 
			
		||||
                array_map(
 | 
			
		||||
                    fn (Scope $s) => $this->translatableStringHelper->localize($s->getName()),
 | 
			
		||||
                    $data['scopes']->toArray()
 | 
			
		||||
                )
 | 
			
		||||
            ),
 | 
			
		||||
        ]];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getTitle()
 | 
			
		||||
    {
 | 
			
		||||
        return 'export.filter.Filter by user scope';
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -12,8 +12,7 @@ declare(strict_types=1);
 | 
			
		||||
namespace Chill\AsideActivityBundle\Form;
 | 
			
		||||
 | 
			
		||||
use Chill\AsideActivityBundle\Entity\AsideActivity;
 | 
			
		||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
 | 
			
		||||
use Chill\AsideActivityBundle\Templating\Entity\CategoryRender;
 | 
			
		||||
use Chill\AsideActivityBundle\Form\Type\PickAsideActivityCategoryType;
 | 
			
		||||
use Chill\MainBundle\Form\Type\ChillDateType;
 | 
			
		||||
use Chill\MainBundle\Form\Type\ChillTextareaType;
 | 
			
		||||
use Chill\MainBundle\Form\Type\PickUserDynamicType;
 | 
			
		||||
@@ -21,8 +20,6 @@ use DateInterval;
 | 
			
		||||
use DateTime;
 | 
			
		||||
use DateTimeImmutable;
 | 
			
		||||
use DateTimeZone;
 | 
			
		||||
use Doctrine\ORM\EntityRepository;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
 | 
			
		||||
use Symfony\Component\Form\AbstractType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer;
 | 
			
		||||
@@ -37,20 +34,16 @@ use function in_array;
 | 
			
		||||
 | 
			
		||||
final class AsideActivityFormType extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    private CategoryRender $categoryRender;
 | 
			
		||||
 | 
			
		||||
    private TokenStorageInterface $storage;
 | 
			
		||||
 | 
			
		||||
    private array $timeChoices;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ParameterBagInterface $parameterBag,
 | 
			
		||||
        TokenStorageInterface $storage,
 | 
			
		||||
        CategoryRender $categoryRender
 | 
			
		||||
        TokenStorageInterface $storage
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->timeChoices = $parameterBag->get('chill_aside_activity.form.time_duration');
 | 
			
		||||
        $this->storage = $storage;
 | 
			
		||||
        $this->categoryRender = $categoryRender;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder, array $options)
 | 
			
		||||
@@ -81,28 +74,10 @@ final class AsideActivityFormType extends AbstractType
 | 
			
		||||
                    'required' => true,
 | 
			
		||||
                ]
 | 
			
		||||
            )
 | 
			
		||||
            ->add(
 | 
			
		||||
                'type',
 | 
			
		||||
                EntityType::class,
 | 
			
		||||
                [
 | 
			
		||||
                    'label' => 'Type',
 | 
			
		||||
                    'required' => true,
 | 
			
		||||
                    'class' => AsideActivityCategory::class,
 | 
			
		||||
                    'placeholder' => 'Choose the activity category',
 | 
			
		||||
                    'query_builder' => static function (EntityRepository $er) {
 | 
			
		||||
                        $qb = $er->createQueryBuilder('ac');
 | 
			
		||||
                        $qb->where($qb->expr()->eq('ac.isActive', 'TRUE'))
 | 
			
		||||
                            ->addOrderBy('ac.ordering', 'ASC');
 | 
			
		||||
 | 
			
		||||
                        return $qb;
 | 
			
		||||
                    },
 | 
			
		||||
                    'choice_label' => function (AsideActivityCategory $asideActivityCategory) {
 | 
			
		||||
                        $options = [];
 | 
			
		||||
 | 
			
		||||
                        return $this->categoryRender->renderString($asideActivityCategory, $options);
 | 
			
		||||
                    },
 | 
			
		||||
                ]
 | 
			
		||||
            )
 | 
			
		||||
            ->add('type', PickAsideActivityCategoryType::class, [
 | 
			
		||||
                'label' => 'Type',
 | 
			
		||||
                'required' => true,
 | 
			
		||||
            ])
 | 
			
		||||
            ->add('duration', ChoiceType::class, $durationTimeOptions)
 | 
			
		||||
            ->add('note', ChillTextareaType::class, [
 | 
			
		||||
                'label' => 'Note',
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,57 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\AsideActivityBundle\Form\Type;
 | 
			
		||||
 | 
			
		||||
use Chill\AsideActivityBundle\Entity\AsideActivityCategory;
 | 
			
		||||
use Chill\AsideActivityBundle\Templating\Entity\CategoryRender;
 | 
			
		||||
use Doctrine\ORM\EntityRepository;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\AbstractType;
 | 
			
		||||
use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
			
		||||
 | 
			
		||||
final class PickAsideActivityCategoryType extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    private CategoryRender $categoryRender;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        CategoryRender $categoryRender
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->categoryRender = $categoryRender;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function configureOptions(OptionsResolver $resolver)
 | 
			
		||||
    {
 | 
			
		||||
        $resolver
 | 
			
		||||
            ->setDefaults([
 | 
			
		||||
                'class' => AsideActivityCategory::class,
 | 
			
		||||
                'placeholder' => 'Choose the activity category',
 | 
			
		||||
                'query_builder' => static function (EntityRepository $er) {
 | 
			
		||||
                    $qb = $er->createQueryBuilder('ac');
 | 
			
		||||
                    $qb->where($qb->expr()->eq('ac.isActive', 'TRUE'))
 | 
			
		||||
                        ->addOrderBy('ac.ordering', 'ASC');
 | 
			
		||||
 | 
			
		||||
                    return $qb;
 | 
			
		||||
                },
 | 
			
		||||
                'choice_label' => function (AsideActivityCategory $asideActivityCategory) {
 | 
			
		||||
                    $options = [];
 | 
			
		||||
 | 
			
		||||
                    return $this->categoryRender->renderString($asideActivityCategory, $options);
 | 
			
		||||
                },
 | 
			
		||||
                'attr' => ['class' => 'select2'],
 | 
			
		||||
            ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getParent(): string
 | 
			
		||||
    {
 | 
			
		||||
        return EntityType::class;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
<div class="{% block crud_content_main_div_class %}col-10 centered{% endblock %}">
 | 
			
		||||
 | 
			
		||||
	{% block crud_content_header %}
 | 
			
		||||
		<h1>{{ ('crud.'~crud_name~'.title_delete')|trans({ '%as_string%': 'Aside Activity' }) }}</h1>
 | 
			
		||||
	{% endblock crud_content_header %}
 | 
			
		||||
@@ -27,4 +27,4 @@
 | 
			
		||||
	</ul>
 | 
			
		||||
 | 
			
		||||
	{{ form_end(form) }}
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -87,5 +87,5 @@
 | 
			
		||||
				</li>
 | 
			
		||||
			</ul>
 | 
			
		||||
		{% endif %}
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
	{% endblock %}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
{% extends '@ChillMain/Admin/layout.html.twig' %}
 | 
			
		||||
{% extends '@ChillMain/layout.html.twig' %}
 | 
			
		||||
 | 
			
		||||
{% block js %}
 | 
			
		||||
    {{ parent() }}
 | 
			
		||||
@@ -14,7 +14,7 @@
 | 
			
		||||
{% include('@ChillMain/CRUD/_new_title.html.twig') %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block admin_content %}
 | 
			
		||||
{% block content %}
 | 
			
		||||
{% embed '@ChillMain/CRUD/_new_content.html.twig' %}
 | 
			
		||||
    {% block content_form_actions_save_and_show %}{% endblock %}
 | 
			
		||||
{% endembed %}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,33 +20,3 @@ services:
 | 
			
		||||
    resource: "../Controller"
 | 
			
		||||
    autowire: true
 | 
			
		||||
    autoconfigure: true
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  ## Exports
 | 
			
		||||
 | 
			
		||||
  # indicators
 | 
			
		||||
  Chill\AsideActivityBundle\Export\Export\CountAsideActivity:
 | 
			
		||||
    autowire: true
 | 
			
		||||
    autoconfigure: true
 | 
			
		||||
    tags:
 | 
			
		||||
      - { name: chill.export, alias: count_asideactivity }
 | 
			
		||||
 | 
			
		||||
  # filters
 | 
			
		||||
  Chill\AsideActivityBundle\Export\Filter\ByDateFilter:
 | 
			
		||||
    autowire: true
 | 
			
		||||
    autoconfigure: true
 | 
			
		||||
    tags:
 | 
			
		||||
      - { name: chill.export_filter, alias: asideactivity_bydate_filter }
 | 
			
		||||
 | 
			
		||||
  Chill\AsideActivityBundle\Export\Filter\ByActivityTypeFilter:
 | 
			
		||||
    autowire: true
 | 
			
		||||
    autoconfigure: true
 | 
			
		||||
    tags:
 | 
			
		||||
      - { name: chill.export_filter, alias: asideactivity_activitytype_filter }
 | 
			
		||||
 | 
			
		||||
  # aggregators
 | 
			
		||||
  Chill\AsideActivityBundle\Export\Aggregator\ByActivityTypeAggregator:
 | 
			
		||||
    autowire: true
 | 
			
		||||
    autoconfigure: true
 | 
			
		||||
    tags:
 | 
			
		||||
      - { name: chill.export_aggregator, alias: asideactivity_activitytype_aggregator }
 | 
			
		||||
 
 | 
			
		||||
@@ -3,11 +3,23 @@ services:
 | 
			
		||||
    autowire: true
 | 
			
		||||
    autoconfigure: true
 | 
			
		||||
 | 
			
		||||
  Chill\AsideActivityBundle\Export\Export\ListAsideActivity:
 | 
			
		||||
      tags:
 | 
			
		||||
          - { name: chill.export, alias: 'list_aside_activity' }
 | 
			
		||||
 | 
			
		||||
  ## Indicators
 | 
			
		||||
  Chill\AsideActivityBundle\Export\Export\CountAsideActivity:
 | 
			
		||||
    tags:
 | 
			
		||||
      - { name: chill.export, alias: 'count_aside_activity' }
 | 
			
		||||
 | 
			
		||||
  Chill\AsideActivityBundle\Export\Export\SumAsideActivityDuration:
 | 
			
		||||
      tags:
 | 
			
		||||
          - { name: chill.export, alias: 'sum_aside_activity_duration' }
 | 
			
		||||
 | 
			
		||||
  Chill\AsideActivityBundle\Export\Export\AvgAsideActivityDuration:
 | 
			
		||||
      tags:
 | 
			
		||||
          - { name: chill.export, alias: 'avg_aside_activity_duration' }
 | 
			
		||||
 | 
			
		||||
  ## Filters
 | 
			
		||||
  chill.aside_activity.export.date_filter:
 | 
			
		||||
    class: Chill\AsideActivityBundle\Export\Filter\ByDateFilter
 | 
			
		||||
@@ -19,9 +31,34 @@ services:
 | 
			
		||||
    tags:
 | 
			
		||||
      - { name: chill.export_filter, alias: 'aside_activity_type_filter' }
 | 
			
		||||
 | 
			
		||||
  chill.aside_activity.export.user_job_filter:
 | 
			
		||||
      class: Chill\AsideActivityBundle\Export\Filter\ByUserJobFilter
 | 
			
		||||
      tags:
 | 
			
		||||
          - { name: chill.export_filter, alias: 'aside_activity_user_job_filter' }
 | 
			
		||||
 | 
			
		||||
  chill.aside_activity.export.user_scope_filter:
 | 
			
		||||
      class: Chill\AsideActivityBundle\Export\Filter\ByUserScopeFilter
 | 
			
		||||
      tags:
 | 
			
		||||
          - { name: chill.export_filter, alias: 'aside_activity_user_scope_filter' }
 | 
			
		||||
 | 
			
		||||
  chill.aside_activity.export.user_filter:
 | 
			
		||||
      class: Chill\AsideActivityBundle\Export\Filter\ByUserFilter
 | 
			
		||||
      tags:
 | 
			
		||||
          - { name: chill.export_filter, alias: 'aside_activity_user_filter' }
 | 
			
		||||
 | 
			
		||||
  ## Aggregators
 | 
			
		||||
 | 
			
		||||
  chill.aside_activity.export.type_aggregator:
 | 
			
		||||
    class: Chill\AsideActivityBundle\Export\Aggregator\ByActivityTypeAggregator
 | 
			
		||||
    tags:
 | 
			
		||||
      - { name: chill.export_aggregator, alias: activity_type_aggregator }
 | 
			
		||||
      - { name: chill.export_aggregator, alias: activity_type_aggregator }
 | 
			
		||||
 | 
			
		||||
  chill.aside_activity.export.user_job_aggregator:
 | 
			
		||||
      class: Chill\AsideActivityBundle\Export\Aggregator\ByUserJobAggregator
 | 
			
		||||
      tags:
 | 
			
		||||
          - { name: chill.export_aggregator, alias: aside_activity_user_job_aggregator }
 | 
			
		||||
 | 
			
		||||
  chill.aside_activity.export.user_scope_aggregator:
 | 
			
		||||
      class: Chill\AsideActivityBundle\Export\Aggregator\ByUserScopeAggregator
 | 
			
		||||
      tags:
 | 
			
		||||
          - { name: chill.export_aggregator, alias: aside_activity_user_scope_aggregator }
 | 
			
		||||
 
 | 
			
		||||
@@ -29,16 +29,16 @@ location: Lieu
 | 
			
		||||
 | 
			
		||||
# Crud
 | 
			
		||||
crud:
 | 
			
		||||
  aside_activity:
 | 
			
		||||
    title_view: Détail de l'activité annexe
 | 
			
		||||
    title_new: Nouvelle activité annexe
 | 
			
		||||
    title_edit: Édition d'une activité annexe
 | 
			
		||||
    title_delete: Supprimer une activité annexe
 | 
			
		||||
    button_delete: Supprimer
 | 
			
		||||
    confirm_message_delete: Êtes-vous sûr de vouloir supprimer cette activité annexe?
 | 
			
		||||
  aside_activity_category:
 | 
			
		||||
    title_new: Nouvelle catégorie d'activité annexe
 | 
			
		||||
    title_edit: Édition d'une catégorie de type d'activité
 | 
			
		||||
    aside_activity:
 | 
			
		||||
        title_view: Détail de l'activité annexe
 | 
			
		||||
        title_new: Nouvelle activité annexe
 | 
			
		||||
        title_edit: Édition d'une activité annexe
 | 
			
		||||
        title_delete: Supprimer une activité annexe
 | 
			
		||||
        button_delete: Supprimer
 | 
			
		||||
        confirm_message_delete: Êtes-vous sûr de vouloir supprimer cette activité annexe?
 | 
			
		||||
    aside_activity_category:
 | 
			
		||||
        title_new: Nouvelle catégorie d'activité annexe
 | 
			
		||||
        title_edit: Édition d'une catégorie de type d'activité
 | 
			
		||||
 | 
			
		||||
#forms
 | 
			
		||||
Create a new aside activity type: Nouvelle categorie d'activité annexe
 | 
			
		||||
@@ -169,18 +169,43 @@ Aside activity configuration: Configuration des activités annexes
 | 
			
		||||
 | 
			
		||||
# exports
 | 
			
		||||
export:
 | 
			
		||||
  Exports of aside activities: Exports des activités annexes
 | 
			
		||||
  Count aside activities: Nombre d'activités annexes
 | 
			
		||||
  Count aside activities by various parameters.: Compte le nombre d'activités annexes selon divers critères
 | 
			
		||||
  filter:
 | 
			
		||||
    Filter by aside activity date: Filtrer les activités annexes par date
 | 
			
		||||
    Filter by aside activity type: Filtrer les activités annexes par type d'activité
 | 
			
		||||
    'Filtered by aside activity type: only %type%': "Filtré par type d'activité annexe: uniquement %type%"
 | 
			
		||||
    This date should be after the date given in "Implied in an aside activity after this date" field: Cette date devrait être postérieure à la date donnée dans le champ "activités annexes après cette date"
 | 
			
		||||
    Aside activities after this date: Actvitités annexes après cette date
 | 
			
		||||
    Aside activities before this date: Actvitités annexes avant cette date
 | 
			
		||||
  aggregator:
 | 
			
		||||
    Group by aside activity type: Grouper les activités annexes par type d'activité
 | 
			
		||||
    Aside activity type: Type d'activité annexe
 | 
			
		||||
    aside_activity:
 | 
			
		||||
        List of aside activities: Liste des activités annexes
 | 
			
		||||
        createdAt: Création
 | 
			
		||||
        updatedAt: Dernière mise à jour
 | 
			
		||||
        agent_id: Utilisateur
 | 
			
		||||
        creator_id: Créateur
 | 
			
		||||
        main_scope: Service principal de l'utilisateur
 | 
			
		||||
        main_center: Centre principal de l'utilisteur
 | 
			
		||||
        aside_activity_type: Catégorie d'activité annexe
 | 
			
		||||
        date: Date
 | 
			
		||||
        duration: Durée
 | 
			
		||||
        note: Note
 | 
			
		||||
 | 
			
		||||
    Exports of aside activities: Exports des activités annexes
 | 
			
		||||
    Count aside activities: Nombre d'activités annexes
 | 
			
		||||
    Count aside activities by various parameters.: Compte le nombre d'activités annexes selon divers critères
 | 
			
		||||
    Average aside activities duration: Durée moyenne des activités annexes
 | 
			
		||||
    Sum aside activities duration: Durée des activités annexes
 | 
			
		||||
    filter:
 | 
			
		||||
        Filter by aside activity date: Filtrer les activités annexes par date
 | 
			
		||||
        Filter by aside activity type: Filtrer les activités annexes par type d'activité
 | 
			
		||||
        'Filtered by aside activity type: only %type%': "Filtré par type d'activité annexe: uniquement %type%"
 | 
			
		||||
        Filtered by aside activities between %dateFrom% and %dateTo%: Filtré par date d'activité annexe, entre %dateFrom% et %dateTo%
 | 
			
		||||
        This date should be after the date given in "Implied in an aside activity after this date" field: Cette date devrait être postérieure à la date donnée dans le champ "activités annexes après cette date"
 | 
			
		||||
        Aside activities after this date: Actvitités annexes après cette date
 | 
			
		||||
        Aside activities before this date: Actvitités annexes avant cette date
 | 
			
		||||
        'Filtered aside activity by user: only %users%': "Filtré par utilisateur: uniquement %users%"
 | 
			
		||||
        Filter aside activity by user: Filtrer par utilisateur
 | 
			
		||||
        'Filtered aside activities by user jobs: only %jobs%': "Filtré par métier des utilisateurs: uniquement %jobs%"
 | 
			
		||||
        Filter by user jobs: Filtrer les activités annexes par métier des utilisateurs
 | 
			
		||||
        'Filtered aside activities by user scope: only %scopes%': "Filtré par service des utilisateur: uniquement %scopes%"
 | 
			
		||||
        Filter by user scope: Filtrer les activités annexes par service d'utilisateur
 | 
			
		||||
    aggregator:
 | 
			
		||||
        Group by aside activity type: Grouper les activités annexes par type d'activité
 | 
			
		||||
        Aside activity type: Type d'activité annexe
 | 
			
		||||
        Aggregate by user job: Grouper les activités annexes par métier des utilisateurs
 | 
			
		||||
        Aggregate by user scope: Grouper les activités annexes par service des utilisateurs
 | 
			
		||||
 | 
			
		||||
# ROLES
 | 
			
		||||
CHILL_ASIDE_ACTIVITY_STATS: Statistiques pour les activités annexes
 | 
			
		||||
 
 | 
			
		||||
@@ -1,102 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Config;
 | 
			
		||||
 | 
			
		||||
class ConfigRepository
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var array
 | 
			
		||||
     */
 | 
			
		||||
    protected $charges;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var array
 | 
			
		||||
     */
 | 
			
		||||
    protected $resources;
 | 
			
		||||
 | 
			
		||||
    public function __construct($resources, $charges)
 | 
			
		||||
    {
 | 
			
		||||
        $this->resources = $resources;
 | 
			
		||||
        $this->charges = $charges;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getChargesKeys(bool $onlyActive = false): array
 | 
			
		||||
    {
 | 
			
		||||
        return array_map(static function ($element) {
 | 
			
		||||
            return $element['key'];
 | 
			
		||||
        }, $this->getCharges($onlyActive));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return array where keys are the resource'key and label the ressource label
 | 
			
		||||
     */
 | 
			
		||||
    public function getChargesLabels(bool $onlyActive = false)
 | 
			
		||||
    {
 | 
			
		||||
        $charges = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($this->getCharges($onlyActive) as $definition) {
 | 
			
		||||
            $charges[$definition['key']] = $this->normalizeLabel($definition['labels']);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $charges;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getResourcesKeys(bool $onlyActive = false): array
 | 
			
		||||
    {
 | 
			
		||||
        return array_map(static function ($element) {
 | 
			
		||||
            return $element['key'];
 | 
			
		||||
        }, $this->getResources($onlyActive));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return array where keys are the resource'key and label the ressource label
 | 
			
		||||
     */
 | 
			
		||||
    public function getResourcesLabels(bool $onlyActive = false)
 | 
			
		||||
    {
 | 
			
		||||
        $resources = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($this->getResources($onlyActive) as $definition) {
 | 
			
		||||
            $resources[$definition['key']] = $this->normalizeLabel($definition['labels']);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $resources;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getCharges(bool $onlyActive = false): array
 | 
			
		||||
    {
 | 
			
		||||
        return $onlyActive ?
 | 
			
		||||
            array_filter($this->charges, static function ($el) {
 | 
			
		||||
                return $el['active'];
 | 
			
		||||
            })
 | 
			
		||||
            : $this->charges;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getResources(bool $onlyActive = false): array
 | 
			
		||||
    {
 | 
			
		||||
        return $onlyActive ?
 | 
			
		||||
            array_filter($this->resources, static function ($el) {
 | 
			
		||||
                return $el['active'];
 | 
			
		||||
            })
 | 
			
		||||
            : $this->resources;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function normalizeLabel($labels)
 | 
			
		||||
    {
 | 
			
		||||
        $normalizedLabels = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($labels as $labelDefinition) {
 | 
			
		||||
            $normalizedLabels[$labelDefinition['lang']] = $labelDefinition['label'];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $normalizedLabels;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,26 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Controller\Admin;
 | 
			
		||||
 | 
			
		||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
 | 
			
		||||
use Symfony\Component\Routing\Annotation\Route;
 | 
			
		||||
 | 
			
		||||
class AdminController extends AbstractController
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @Route("/{_locale}/admin/budget", name="chill_admin_budget")
 | 
			
		||||
     */
 | 
			
		||||
    public function indexAdminAction()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->render('@ChillBudget/Admin/index.html.twig');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,28 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Controller\Admin;
 | 
			
		||||
 | 
			
		||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
 | 
			
		||||
use Chill\MainBundle\Pagination\PaginatorInterface;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\HttpFoundation\Request;
 | 
			
		||||
 | 
			
		||||
class ChargeKindController extends CRUDController
 | 
			
		||||
{
 | 
			
		||||
    protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
 | 
			
		||||
    {
 | 
			
		||||
        /** @var QueryBuilder $query */
 | 
			
		||||
        $query->addOrderBy('e.ordering', 'ASC');
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,28 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Controller\Admin;
 | 
			
		||||
 | 
			
		||||
use Chill\MainBundle\CRUD\Controller\CRUDController;
 | 
			
		||||
use Chill\MainBundle\Pagination\PaginatorInterface;
 | 
			
		||||
use Doctrine\ORM\QueryBuilder;
 | 
			
		||||
use Symfony\Component\HttpFoundation\Request;
 | 
			
		||||
 | 
			
		||||
class ResourceKindController extends CRUDController
 | 
			
		||||
{
 | 
			
		||||
    protected function orderQuery(string $action, $query, Request $request, PaginatorInterface $paginator)
 | 
			
		||||
    {
 | 
			
		||||
        /** @var QueryBuilder $query */
 | 
			
		||||
        $query->addOrderBy('e.ordering', 'ASC');
 | 
			
		||||
 | 
			
		||||
        return $query;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -11,6 +11,10 @@ declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\DependencyInjection;
 | 
			
		||||
 | 
			
		||||
use Chill\BudgetBundle\Controller\Admin\ChargeKindController;
 | 
			
		||||
use Chill\BudgetBundle\Controller\Admin\ResourceKindController;
 | 
			
		||||
use Chill\BudgetBundle\Entity\ChargeKind;
 | 
			
		||||
use Chill\BudgetBundle\Entity\ResourceKind;
 | 
			
		||||
use Chill\BudgetBundle\Security\Authorization\BudgetElementVoter;
 | 
			
		||||
use Symfony\Component\Config\FileLocator;
 | 
			
		||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
 | 
			
		||||
@@ -31,8 +35,8 @@ class ChillBudgetExtension extends Extension implements PrependExtensionInterfac
 | 
			
		||||
        $config = $this->processConfiguration($configuration, $configs);
 | 
			
		||||
 | 
			
		||||
        $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../config'));
 | 
			
		||||
        $loader->load('services/config.yaml');
 | 
			
		||||
        $loader->load('services/form.yaml');
 | 
			
		||||
        $loader->load('services/repository.yaml');
 | 
			
		||||
        $loader->load('services/security.yaml');
 | 
			
		||||
        $loader->load('services/controller.yaml');
 | 
			
		||||
        $loader->load('services/templating.yaml');
 | 
			
		||||
@@ -48,6 +52,7 @@ class ChillBudgetExtension extends Extension implements PrependExtensionInterfac
 | 
			
		||||
    {
 | 
			
		||||
        $this->prependAuthorization($container);
 | 
			
		||||
        $this->prependRoutes($container);
 | 
			
		||||
        $this->prependCruds($container);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /** (non-PHPdoc).
 | 
			
		||||
@@ -75,6 +80,56 @@ class ChillBudgetExtension extends Extension implements PrependExtensionInterfac
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function prependCruds(ContainerBuilder $container)
 | 
			
		||||
    {
 | 
			
		||||
        $container->prependExtensionConfig('chill_main', [
 | 
			
		||||
            'cruds' => [
 | 
			
		||||
                [
 | 
			
		||||
                    'class' => ChargeKind::class,
 | 
			
		||||
                    'name' => 'charge_kind',
 | 
			
		||||
                    'base_path' => '/admin/budget/charge-kind',
 | 
			
		||||
                    'form_class' => \Chill\BudgetBundle\Form\Admin\ChargeKindType::class,
 | 
			
		||||
                    'controller' => ChargeKindController::class,
 | 
			
		||||
                    'actions' => [
 | 
			
		||||
                        'index' => [
 | 
			
		||||
                            'role' => 'ROLE_ADMIN',
 | 
			
		||||
                            'template' => '@ChillBudget/Admin/Charge/index.html.twig',
 | 
			
		||||
                        ],
 | 
			
		||||
                        'new' => [
 | 
			
		||||
                            'role' => 'ROLE_ADMIN',
 | 
			
		||||
                            'template' => '@ChillBudget/Admin/Charge/new.html.twig',
 | 
			
		||||
                        ],
 | 
			
		||||
                        'edit' => [
 | 
			
		||||
                            'role' => 'ROLE_ADMIN',
 | 
			
		||||
                            'template' => '@ChillBudget/Admin/Charge/edit.html.twig',
 | 
			
		||||
                        ],
 | 
			
		||||
                    ],
 | 
			
		||||
                ],
 | 
			
		||||
                [
 | 
			
		||||
                    'class' => ResourceKind::class,
 | 
			
		||||
                    'name' => 'resource_kind',
 | 
			
		||||
                    'base_path' => '/admin/budget/resource-kind',
 | 
			
		||||
                    'form_class' => \Chill\BudgetBundle\Form\Admin\ResourceKindType::class,
 | 
			
		||||
                    'controller' => ResourceKindController::class,
 | 
			
		||||
                    'actions' => [
 | 
			
		||||
                        'index' => [
 | 
			
		||||
                            'role' => 'ROLE_ADMIN',
 | 
			
		||||
                            'template' => '@ChillBudget/Admin/Resource/index.html.twig',
 | 
			
		||||
                        ],
 | 
			
		||||
                        'new' => [
 | 
			
		||||
                            'role' => 'ROLE_ADMIN',
 | 
			
		||||
                            'template' => '@ChillBudget/Admin/Resource/new.html.twig',
 | 
			
		||||
                        ],
 | 
			
		||||
                        'edit' => [
 | 
			
		||||
                            'role' => 'ROLE_ADMIN',
 | 
			
		||||
                            'template' => '@ChillBudget/Admin/Resource/edit.html.twig',
 | 
			
		||||
                        ],
 | 
			
		||||
                    ],
 | 
			
		||||
                ],
 | 
			
		||||
            ],
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function storeConfig($position, array $config, ContainerBuilder $container)
 | 
			
		||||
    {
 | 
			
		||||
        $container
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ class Configuration implements ConfigurationInterface
 | 
			
		||||
 | 
			
		||||
                // ressources
 | 
			
		||||
            ->arrayNode('resources')->defaultValue([])
 | 
			
		||||
            ->setDeprecated('Chill', '2.0', 'Since the introduction of budget admin entities, config is no longer used')
 | 
			
		||||
            ->arrayPrototype()
 | 
			
		||||
            ->children()
 | 
			
		||||
            ->scalarNode('key')->isRequired()->cannotBeEmpty()
 | 
			
		||||
@@ -49,6 +50,7 @@ class Configuration implements ConfigurationInterface
 | 
			
		||||
            ->end()
 | 
			
		||||
            ->end()
 | 
			
		||||
            ->arrayNode('charges')->defaultValue([])
 | 
			
		||||
            ->setDeprecated('Chill', '2.0', 'Since the introduction of budget admin entities, config is no longer used')
 | 
			
		||||
            ->arrayPrototype()
 | 
			
		||||
            ->children()
 | 
			
		||||
            ->scalarNode('key')->isRequired()->cannotBeEmpty()
 | 
			
		||||
 
 | 
			
		||||
@@ -75,7 +75,7 @@ abstract class AbstractElement
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(name="type", type="string", length=255)
 | 
			
		||||
     */
 | 
			
		||||
    private string $type;
 | 
			
		||||
    private string $type = '';
 | 
			
		||||
 | 
			
		||||
    /*Getters and Setters */
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,12 @@ class Charge extends AbstractElement implements HasCentersInterface
 | 
			
		||||
        self::HELP_NOT_RELEVANT,
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToOne(targetEntity=ChargeKind::class, inversedBy="AbstractElement")
 | 
			
		||||
     * @ORM\JoinColumn
 | 
			
		||||
     */
 | 
			
		||||
    private ?ChargeKind $charge = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var string
 | 
			
		||||
     * @ORM\Column(name="help", type="string", nullable=true)
 | 
			
		||||
@@ -66,6 +72,11 @@ class Charge extends AbstractElement implements HasCentersInterface
 | 
			
		||||
        return $this->getHousehold()->getCurrentPersons()->map(static fn (Person $p) => $p->getCenter())->toArray();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getCharge(): ?ChargeKind
 | 
			
		||||
    {
 | 
			
		||||
        return $this->charge;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getHelp()
 | 
			
		||||
    {
 | 
			
		||||
        return $this->help;
 | 
			
		||||
@@ -91,6 +102,13 @@ class Charge extends AbstractElement implements HasCentersInterface
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setCharge(?ChargeKind $charge): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->charge = $charge;
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setHelp($help)
 | 
			
		||||
    {
 | 
			
		||||
        $this->help = $help;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										115
									
								
								src/Bundle/ChillBudgetBundle/Entity/ChargeKind.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/Bundle/ChillBudgetBundle/Entity/ChargeKind.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Entity;
 | 
			
		||||
 | 
			
		||||
use Doctrine\ORM\Mapping as ORM;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
 | 
			
		||||
use Symfony\Component\Validator\Constraints as Assert;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Type of charge.
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\Table(name="chill_budget.charge_type",
 | 
			
		||||
 *     uniqueConstraints={@ORM\UniqueConstraint(name="charge_kind_unique_type_idx", fields={"kind"})}
 | 
			
		||||
 * )
 | 
			
		||||
 * @ORM\Entity
 | 
			
		||||
 * @UniqueEntity(fields={"kind"})
 | 
			
		||||
 */
 | 
			
		||||
class ChargeKind
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Id
 | 
			
		||||
     * @ORM\GeneratedValue
 | 
			
		||||
     * @ORM\Column(type="integer")
 | 
			
		||||
     */
 | 
			
		||||
    private ?int $id = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="boolean", options={"default": true})
 | 
			
		||||
     */
 | 
			
		||||
    private bool $isActive = true;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="string", length=255, options={"default": ""}, nullable=false)
 | 
			
		||||
     * @Assert\Regex(pattern="/^[a-z0-9\-_]{1,}$/", message="budget.admin.form.kind.only_alphanumeric")
 | 
			
		||||
     * @Assert\Length(min=3)
 | 
			
		||||
     */
 | 
			
		||||
    private string $kind = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="json", length=255, options={"default": "[]"})
 | 
			
		||||
     */
 | 
			
		||||
    private array $name = [];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="float", options={"default": 0.00})
 | 
			
		||||
     */
 | 
			
		||||
    private float $ordering = 0.00;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="json", length=255, options={"default": "[]"})
 | 
			
		||||
     */
 | 
			
		||||
    private array $tags = [];
 | 
			
		||||
 | 
			
		||||
    public function getId(): ?int
 | 
			
		||||
    {
 | 
			
		||||
        return $this->id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getIsActive(): bool
 | 
			
		||||
    {
 | 
			
		||||
        return $this->isActive;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getKind(): ?string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->kind;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getName(): ?array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getOrdering(): float
 | 
			
		||||
    {
 | 
			
		||||
        return $this->ordering;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setIsActive(bool $isActive): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->isActive = $isActive;
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setKind(?string $kind): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->kind = $kind;
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setName(array $name): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->name = $name;
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setOrdering(float $ordering): ChargeKind
 | 
			
		||||
    {
 | 
			
		||||
        $this->ordering = $ordering;
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -31,6 +31,12 @@ class Resource extends AbstractElement implements HasCentersInterface
 | 
			
		||||
     */
 | 
			
		||||
    private ?int $id = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\ManyToOne(targetEntity=ResourceKind::class, inversedBy="AbstractElement")
 | 
			
		||||
     * @ORM\JoinColumn
 | 
			
		||||
     */
 | 
			
		||||
    private ?ResourceKind $resource = null;
 | 
			
		||||
 | 
			
		||||
    public function __construct()
 | 
			
		||||
    {
 | 
			
		||||
        $this->setStartDate(new DateTimeImmutable('today'));
 | 
			
		||||
@@ -55,6 +61,11 @@ class Resource extends AbstractElement implements HasCentersInterface
 | 
			
		||||
        return $this->id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getResource(): ?ResourceKind
 | 
			
		||||
    {
 | 
			
		||||
        return $this->resource;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function isCharge(): bool
 | 
			
		||||
    {
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -64,4 +75,11 @@ class Resource extends AbstractElement implements HasCentersInterface
 | 
			
		||||
    {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setResource(?ResourceKind $resource): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->resource = $resource;
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										115
									
								
								src/Bundle/ChillBudgetBundle/Entity/ResourceKind.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/Bundle/ChillBudgetBundle/Entity/ResourceKind.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Entity;
 | 
			
		||||
 | 
			
		||||
use Doctrine\ORM\Mapping as ORM;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
 | 
			
		||||
use Symfony\Component\Validator\Constraints as Assert;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Type of resource.
 | 
			
		||||
 *
 | 
			
		||||
 * @ORM\Table(name="chill_budget.resource_type", uniqueConstraints={
 | 
			
		||||
 *     @ORM\UniqueConstraint(name="resource_kind_unique_type_idx", fields={"kind"})
 | 
			
		||||
 * })
 | 
			
		||||
 * @ORM\Entity
 | 
			
		||||
 * @UniqueEntity(fields={"kind"})
 | 
			
		||||
 */
 | 
			
		||||
class ResourceKind
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Id
 | 
			
		||||
     * @ORM\GeneratedValue
 | 
			
		||||
     * @ORM\Column(type="integer")
 | 
			
		||||
     */
 | 
			
		||||
    private ?int $id = null;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="boolean", options={"default": true})
 | 
			
		||||
     */
 | 
			
		||||
    private bool $isActive = true;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="string", length=255, nullable=false, options={"default": ""})
 | 
			
		||||
     * @Assert\Regex(pattern="/^[a-z0-9\-_]{1,}$/", message="budget.admin.form.kind.only_alphanumeric")
 | 
			
		||||
     * @Assert\Length(min=3)
 | 
			
		||||
     */
 | 
			
		||||
    private string $kind = '';
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="json", length=255, options={"default": "[]"})
 | 
			
		||||
     */
 | 
			
		||||
    private array $name = [];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="float", options={"default": 0.00})
 | 
			
		||||
     */
 | 
			
		||||
    private float $ordering = 0.00;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @ORM\Column(type="json", length=255, options={"default": "[]"})
 | 
			
		||||
     */
 | 
			
		||||
    private array $tags = [];
 | 
			
		||||
 | 
			
		||||
    public function getId(): ?int
 | 
			
		||||
    {
 | 
			
		||||
        return $this->id;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getIsActive(): bool
 | 
			
		||||
    {
 | 
			
		||||
        return $this->isActive;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getKind(): ?string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->kind;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getName(): ?array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getOrdering(): float
 | 
			
		||||
    {
 | 
			
		||||
        return $this->ordering;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setIsActive(bool $isActive): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->isActive = $isActive;
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setKind(?string $kind): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->kind = $kind;
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setName(array $name): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->name = $name;
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function setOrdering(float $ordering): self
 | 
			
		||||
    {
 | 
			
		||||
        $this->ordering = $ordering;
 | 
			
		||||
 | 
			
		||||
        return $this;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								src/Bundle/ChillBudgetBundle/Form/Admin/ChargeKindType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/Bundle/ChillBudgetBundle/Form/Admin/ChargeKindType.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Form\Admin;
 | 
			
		||||
 | 
			
		||||
use Chill\BudgetBundle\Entity\ChargeKind;
 | 
			
		||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
 | 
			
		||||
use Symfony\Component\Form\AbstractType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
			
		||||
 | 
			
		||||
class ChargeKindType extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder, array $options)
 | 
			
		||||
    {
 | 
			
		||||
        $builder
 | 
			
		||||
            ->add('name', TranslatableStringFormType::class, [
 | 
			
		||||
                'label' => 'Title',
 | 
			
		||||
            ])
 | 
			
		||||
            ->add('kind', TextType::class, [
 | 
			
		||||
                'label' => 'budget.admin.form.Charge_kind_key',
 | 
			
		||||
                'help' => 'budget.admin.form.This kind must contains only alphabeticals characters, and dashes. This string is in use during document generation. Changes may have side effect on document'
 | 
			
		||||
            ])
 | 
			
		||||
            ->add('ordering', NumberType::class)
 | 
			
		||||
            ->add('isActive', CheckboxType::class, [
 | 
			
		||||
                'label' => 'Actif ?',
 | 
			
		||||
                'required' => false,
 | 
			
		||||
            ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function configureOptions(OptionsResolver $resolver)
 | 
			
		||||
    {
 | 
			
		||||
        $resolver
 | 
			
		||||
            ->setDefault('class', ChargeKind::class);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								src/Bundle/ChillBudgetBundle/Form/Admin/ResourceKindType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/Bundle/ChillBudgetBundle/Form/Admin/ResourceKindType.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Form\Admin;
 | 
			
		||||
 | 
			
		||||
use Chill\BudgetBundle\Entity\ResourceKind;
 | 
			
		||||
use Chill\MainBundle\Form\Type\TranslatableStringFormType;
 | 
			
		||||
use Symfony\Component\Form\AbstractType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
			
		||||
 | 
			
		||||
class ResourceKindType extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder, array $options)
 | 
			
		||||
    {
 | 
			
		||||
        $builder
 | 
			
		||||
            ->add('name', TranslatableStringFormType::class, [
 | 
			
		||||
                'label' => 'Title',
 | 
			
		||||
            ])
 | 
			
		||||
            ->add('kind', TextType::class, [
 | 
			
		||||
                'label' => 'budget.admin.form.Resource_kind_key',
 | 
			
		||||
                'help' => 'budget.admin.form.This kind must contains only alphabeticals characters, and dashes. This string is in use during document generation. Changes may have side effect on document'
 | 
			
		||||
            ])
 | 
			
		||||
            ->add('ordering', NumberType::class)
 | 
			
		||||
            ->add('isActive', CheckboxType::class, [
 | 
			
		||||
                'label' => 'Actif ?',
 | 
			
		||||
                'required' => false,
 | 
			
		||||
            ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function configureOptions(OptionsResolver $resolver)
 | 
			
		||||
    {
 | 
			
		||||
        $resolver
 | 
			
		||||
            ->setDefault('class', ResourceKind::class);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -11,41 +11,51 @@ declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Form;
 | 
			
		||||
 | 
			
		||||
use Chill\BudgetBundle\Config\ConfigRepository;
 | 
			
		||||
use Chill\BudgetBundle\Entity\Charge;
 | 
			
		||||
use Chill\BudgetBundle\Entity\ChargeKind;
 | 
			
		||||
use Chill\BudgetBundle\Repository\ChargeKindRepository;
 | 
			
		||||
use Chill\MainBundle\Form\Type\ChillDateType;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\AbstractType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
			
		||||
 | 
			
		||||
use function array_flip;
 | 
			
		||||
use function asort;
 | 
			
		||||
use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
 | 
			
		||||
class ChargeType extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    protected ConfigRepository $configRepository;
 | 
			
		||||
 | 
			
		||||
    protected TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    private ChargeKindRepository $repository;
 | 
			
		||||
 | 
			
		||||
    private TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ConfigRepository $configRepository,
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        ChargeKindRepository $repository,
 | 
			
		||||
        TranslatorInterface $translator
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->configRepository = $configRepository;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
        $this->repository = $repository;
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder, array $options)
 | 
			
		||||
    {
 | 
			
		||||
        $builder
 | 
			
		||||
            ->add('type', ChoiceType::class, [
 | 
			
		||||
                'choices' => $this->getTypes(),
 | 
			
		||||
                'placeholder' => 'Choose a charge type',
 | 
			
		||||
                'attr' => ['class' => ' select2 '],
 | 
			
		||||
            ->add('charge', EntityType::class, [
 | 
			
		||||
                'class' => ChargeKind::class,
 | 
			
		||||
                'choices' => $this->repository->findAllActive(),
 | 
			
		||||
                'label' => 'Charge type',
 | 
			
		||||
                'required' => true,
 | 
			
		||||
                'placeholder' => $this->translator->trans('admin.form.Choose the type of charge'),
 | 
			
		||||
                'choice_label' => function (ChargeKind $resource) {
 | 
			
		||||
                    return $this->translatableStringHelper->localize($resource->getName());
 | 
			
		||||
                },
 | 
			
		||||
                'attr' => ['class' => 'select2'],
 | 
			
		||||
            ])
 | 
			
		||||
            ->add('amount', MoneyType::class)
 | 
			
		||||
            ->add('comment', TextareaType::class, [
 | 
			
		||||
@@ -99,19 +109,4 @@ class ChargeType extends AbstractType
 | 
			
		||||
    {
 | 
			
		||||
        return 'chill_budgetbundle_charge';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getTypes()
 | 
			
		||||
    {
 | 
			
		||||
        $charges = $this->configRepository
 | 
			
		||||
            ->getChargesLabels(true);
 | 
			
		||||
 | 
			
		||||
        // rewrite labels to filter in language
 | 
			
		||||
        foreach ($charges as $key => $labels) {
 | 
			
		||||
            $charges[$key] = $this->translatableStringHelper->localize($labels);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        asort($charges);
 | 
			
		||||
 | 
			
		||||
        return array_flip($charges);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -11,41 +11,50 @@ declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Form;
 | 
			
		||||
 | 
			
		||||
use Chill\BudgetBundle\Config\ConfigRepository;
 | 
			
		||||
use Chill\BudgetBundle\Entity\Resource;
 | 
			
		||||
use Chill\BudgetBundle\Entity\ResourceKind;
 | 
			
		||||
use Chill\BudgetBundle\Repository\ResourceKindRepository;
 | 
			
		||||
use Chill\MainBundle\Form\Type\ChillDateType;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
 | 
			
		||||
use Symfony\Component\Form\AbstractType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
 | 
			
		||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
 | 
			
		||||
use Symfony\Component\Form\FormBuilderInterface;
 | 
			
		||||
use Symfony\Component\OptionsResolver\OptionsResolver;
 | 
			
		||||
 | 
			
		||||
use function array_flip;
 | 
			
		||||
use Symfony\Contracts\Translation\TranslatorInterface;
 | 
			
		||||
 | 
			
		||||
class ResourceType extends AbstractType
 | 
			
		||||
{
 | 
			
		||||
    protected ConfigRepository $configRepository;
 | 
			
		||||
 | 
			
		||||
    protected TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    private ResourceKindRepository $repository;
 | 
			
		||||
 | 
			
		||||
    private TranslatorInterface $translator;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ConfigRepository $configRepository,
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        ResourceKindRepository $repository,
 | 
			
		||||
        TranslatorInterface $translator
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->configRepository = $configRepository;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
        $this->repository = $repository;
 | 
			
		||||
        $this->translator = $translator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildForm(FormBuilderInterface $builder, array $options)
 | 
			
		||||
    {
 | 
			
		||||
        $builder
 | 
			
		||||
            ->add('type', ChoiceType::class, [
 | 
			
		||||
                'choices' => $this->getTypes(),
 | 
			
		||||
                'placeholder' => 'Choose a resource type',
 | 
			
		||||
                'label' => 'Resource element type',
 | 
			
		||||
                'attr' => ['class' => ' select2 '],
 | 
			
		||||
            ->add('resource', EntityType::class, [
 | 
			
		||||
                'class' => ResourceKind::class,
 | 
			
		||||
                'choices' => $this->repository->findAllActive(),
 | 
			
		||||
                'label' => 'Resource type',
 | 
			
		||||
                'required' => true,
 | 
			
		||||
                'placeholder' => $this->translator->trans('admin.form.Choose the type of resource'),
 | 
			
		||||
                'choice_label' => function (ResourceKind $resource) {
 | 
			
		||||
                    return $this->translatableStringHelper->localize($resource->getName());
 | 
			
		||||
                },
 | 
			
		||||
                'attr' => ['class' => 'select2'],
 | 
			
		||||
            ])
 | 
			
		||||
            ->add('amount', MoneyType::class)
 | 
			
		||||
            ->add('comment', TextareaType::class, [
 | 
			
		||||
@@ -83,19 +92,4 @@ class ResourceType extends AbstractType
 | 
			
		||||
    {
 | 
			
		||||
        return 'chill_budgetbundle_resource';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getTypes()
 | 
			
		||||
    {
 | 
			
		||||
        $resources = $this->configRepository
 | 
			
		||||
            ->getResourcesLabels(true);
 | 
			
		||||
 | 
			
		||||
        // rewrite labels to filter in language
 | 
			
		||||
        foreach ($resources as $key => $labels) {
 | 
			
		||||
            $resources[$key] = $this->translatableStringHelper->localize($labels);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        asort($resources);
 | 
			
		||||
 | 
			
		||||
        return array_flip($resources);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										62
									
								
								src/Bundle/ChillBudgetBundle/Menu/AdminMenuBuilder.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/Bundle/ChillBudgetBundle/Menu/AdminMenuBuilder.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Menu;
 | 
			
		||||
 | 
			
		||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
 | 
			
		||||
use Knp\Menu\MenuItem;
 | 
			
		||||
use Symfony\Component\Security\Core\Security;
 | 
			
		||||
 | 
			
		||||
final class AdminMenuBuilder implements LocalMenuBuilderInterface
 | 
			
		||||
{
 | 
			
		||||
    private Security $security;
 | 
			
		||||
 | 
			
		||||
    public function __construct(Security $security)
 | 
			
		||||
    {
 | 
			
		||||
        $this->security = $security;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function buildMenu($menuId, MenuItem $menu, array $parameters)
 | 
			
		||||
    {
 | 
			
		||||
        // all the entries below must have ROLE_ADMIN permissions
 | 
			
		||||
        if (!$this->security->isGranted('ROLE_ADMIN')) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $menu->addChild('Budget', [
 | 
			
		||||
            'route' => 'chill_admin_budget',
 | 
			
		||||
        ])
 | 
			
		||||
            ->setAttribute('class', 'list-group-item-header')
 | 
			
		||||
            ->setExtras([
 | 
			
		||||
                'order' => 7050,
 | 
			
		||||
                'explain' => 'Budget resource and charge type configuration',
 | 
			
		||||
            ]);
 | 
			
		||||
        $menu
 | 
			
		||||
            ->addChild('admin.menu.Resource types', [
 | 
			
		||||
                'route' => 'chill_crud_resource_kind_index',
 | 
			
		||||
            ])
 | 
			
		||||
            ->setExtras([
 | 
			
		||||
                'order' => 7060,
 | 
			
		||||
            ]);
 | 
			
		||||
        $menu
 | 
			
		||||
            ->addChild('admin.menu.Charge types', [
 | 
			
		||||
                'route' => 'chill_crud_charge_kind_index',
 | 
			
		||||
            ])
 | 
			
		||||
            ->setExtras([
 | 
			
		||||
                'order' => 7070,
 | 
			
		||||
            ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static function getMenuIds(): array
 | 
			
		||||
    {
 | 
			
		||||
        return ['admin_section', 'admin_budget'];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,89 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Repository;
 | 
			
		||||
 | 
			
		||||
use Chill\BudgetBundle\Entity\ChargeKind;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use Doctrine\ORM\EntityRepository;
 | 
			
		||||
 | 
			
		||||
final class ChargeKindRepository implements ChargeKindRepositoryInterface
 | 
			
		||||
{
 | 
			
		||||
    private EntityRepository $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(EntityManagerInterface $entityManager)
 | 
			
		||||
    {
 | 
			
		||||
        $this->repository = $entityManager->getRepository(ChargeKind::class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function find($id): ?ChargeKind
 | 
			
		||||
    {
 | 
			
		||||
        return $this->repository->find($id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return ChargeType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findAll(): array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->repository->findAll();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return ChargeType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findAllActive(): array
 | 
			
		||||
    {
 | 
			
		||||
        $qb = $this->repository->createQueryBuilder('c');
 | 
			
		||||
 | 
			
		||||
        return $qb
 | 
			
		||||
            ->select('c')
 | 
			
		||||
            ->where($qb->expr()->eq('c.isActive', 'true'))
 | 
			
		||||
            ->orderBy('c.ordering', 'ASC')
 | 
			
		||||
            ->getQuery()
 | 
			
		||||
            ->getResult()
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return ChargeType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findAllByType(string $type): array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->findBy(['elementType' => $type]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param mixed|null $limit
 | 
			
		||||
     * @param mixed|null $offset
 | 
			
		||||
     *
 | 
			
		||||
     * @return ChargeType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function findOneBy(array $criteria): ?ChargeKind
 | 
			
		||||
    {
 | 
			
		||||
        return $this->repository->findOneBy($criteria);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function findOneByKind(string $kind): ?ChargeKind
 | 
			
		||||
    {
 | 
			
		||||
        return $this->repository->findOneBy(['kind' => $kind]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getClassName(): string
 | 
			
		||||
    {
 | 
			
		||||
        return ChargeKind::class;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,49 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Repository;
 | 
			
		||||
 | 
			
		||||
use Chill\BudgetBundle\Entity\ChargeKind;
 | 
			
		||||
use Doctrine\Persistence\ObjectRepository;
 | 
			
		||||
 | 
			
		||||
interface ChargeKindRepositoryInterface extends ObjectRepository
 | 
			
		||||
{
 | 
			
		||||
    public function find($id): ?ChargeKind;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return ChargeType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findAll(): array;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return ChargeType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findAllActive(): array;
 | 
			
		||||
 | 
			
		||||
    public function findOneByKind(string $kind): ?ChargeKind;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return ChargeType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findAllByType(string $type): array;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param mixed|null $limit
 | 
			
		||||
     * @param mixed|null $offset
 | 
			
		||||
     *
 | 
			
		||||
     * @return ChargeType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array;
 | 
			
		||||
 | 
			
		||||
    public function findOneBy(array $criteria): ?ChargeKind;
 | 
			
		||||
 | 
			
		||||
    public function getClassName(): string;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,89 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Repository;
 | 
			
		||||
 | 
			
		||||
use Chill\BudgetBundle\Entity\ResourceKind;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use Doctrine\ORM\EntityRepository;
 | 
			
		||||
 | 
			
		||||
final class ResourceKindRepository implements ResourceKindRepositoryInterface
 | 
			
		||||
{
 | 
			
		||||
    private EntityRepository $repository;
 | 
			
		||||
 | 
			
		||||
    public function __construct(EntityManagerInterface $entityManager)
 | 
			
		||||
    {
 | 
			
		||||
        $this->repository = $entityManager->getRepository(ResourceKind::class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function find($id): ?ResourceKind
 | 
			
		||||
    {
 | 
			
		||||
        return $this->repository->find($id);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return ResourceType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findAll(): array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->repository->findAll();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return ResourceType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findAllActive(): array
 | 
			
		||||
    {
 | 
			
		||||
        $qb = $this->repository->createQueryBuilder('r');
 | 
			
		||||
 | 
			
		||||
        return $qb
 | 
			
		||||
            ->select('r')
 | 
			
		||||
            ->where($qb->expr()->eq('r.isActive', 'true'))
 | 
			
		||||
            ->orderBy('r.ordering', 'ASC')
 | 
			
		||||
            ->getQuery()
 | 
			
		||||
            ->getResult()
 | 
			
		||||
        ;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return ResourceType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findAllByType(string $type): array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->findBy(['elementType' => $type]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param mixed|null $limit
 | 
			
		||||
     * @param mixed|null $offset
 | 
			
		||||
     *
 | 
			
		||||
     * @return ResourceType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
 | 
			
		||||
    {
 | 
			
		||||
        return $this->repository->findBy($criteria, $orderBy, $limit, $offset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function findOneBy(array $criteria): ?ResourceKind
 | 
			
		||||
    {
 | 
			
		||||
        return $this->repository->findOneBy($criteria);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function findOneByKind(string $kind): ?ResourceKind
 | 
			
		||||
    {
 | 
			
		||||
        return $this->repository->findOneBy(['kind' => $kind]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getClassName(): string
 | 
			
		||||
    {
 | 
			
		||||
        return ResourceKind::class;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,49 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Repository;
 | 
			
		||||
 | 
			
		||||
use Chill\BudgetBundle\Entity\ResourceKind;
 | 
			
		||||
use Doctrine\Persistence\ObjectRepository;
 | 
			
		||||
 | 
			
		||||
interface ResourceKindRepositoryInterface extends ObjectRepository
 | 
			
		||||
{
 | 
			
		||||
    public function find($id): ?ResourceKind;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return ResourceType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findAll(): array;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return ResourceType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findAllActive(): array;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return ResourceType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findAllByType(string $type): array;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param mixed|null $limit
 | 
			
		||||
     * @param mixed|null $offset
 | 
			
		||||
     *
 | 
			
		||||
     * @return ResourceType[]
 | 
			
		||||
     */
 | 
			
		||||
    public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array;
 | 
			
		||||
 | 
			
		||||
    public function findOneBy(array $criteria): ?ResourceKind;
 | 
			
		||||
 | 
			
		||||
    public function findOneByKind(string $kind): ?ResourceKind;
 | 
			
		||||
 | 
			
		||||
    public function getClassName(): string;
 | 
			
		||||
}
 | 
			
		||||
@@ -34,7 +34,7 @@ class ResourceRepository extends EntityRepository
 | 
			
		||||
            //->andWhere('c.startDate < :date')
 | 
			
		||||
            // TODO: there is a misconception here, the end date must be lower or null. startDate are never null
 | 
			
		||||
            //->andWhere('c.startDate < :date OR c.startDate IS NULL');
 | 
			
		||||
;
 | 
			
		||||
        ;
 | 
			
		||||
 | 
			
		||||
        if (null !== $sort) {
 | 
			
		||||
            $qb->orderBy($sort);
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,12 @@
 | 
			
		||||
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
 | 
			
		||||
 | 
			
		||||
{% block title %}
 | 
			
		||||
    {% include('@ChillMain/CRUD/_edit_title.html.twig') %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block admin_content %}
 | 
			
		||||
    {% embed '@ChillMain/CRUD/_edit_content.html.twig' %}
 | 
			
		||||
        {% block content_form_actions_view %}{% endblock %}
 | 
			
		||||
        {% block content_form_actions_save_and_show %}{% endblock %}
 | 
			
		||||
    {% endembed %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@@ -0,0 +1,54 @@
 | 
			
		||||
{% extends '@ChillMain/Admin/layoutWithVerticalMenu.html.twig' %}
 | 
			
		||||
 | 
			
		||||
{% block title %}{{ 'admin.title.Charge Type List'|trans }}{% endblock title %}
 | 
			
		||||
 | 
			
		||||
{% block admin_content %}
 | 
			
		||||
 | 
			
		||||
    <h1>{{ 'admin.title.Charge Type List'|trans }}</h1>
 | 
			
		||||
 | 
			
		||||
	<table class="records_list table table-bordered border-dark">
 | 
			
		||||
		<thead>
 | 
			
		||||
			<tr>
 | 
			
		||||
                <th>{{ 'Ordering'|trans }}</th>
 | 
			
		||||
				<th>{{ 'Name'|trans }}</th>
 | 
			
		||||
				<th>{{ 'Active'|trans }}</th>
 | 
			
		||||
                <th> </th>
 | 
			
		||||
			</tr>
 | 
			
		||||
		</thead>
 | 
			
		||||
		<tbody>
 | 
			
		||||
			{% for entity in entities %}
 | 
			
		||||
				<tr>
 | 
			
		||||
                    <td>{{ entity.ordering }}</td>
 | 
			
		||||
					<td>
 | 
			
		||||
                        {{ entity|chill_entity_render_box }}<br/>
 | 
			
		||||
                        <strong>{{ 'budget.admin.form.Charge_kind_key'|trans }} :</strong> <code>{{ entity.kind }}</code>
 | 
			
		||||
                    </td>
 | 
			
		||||
					<td style="text-align:center;">
 | 
			
		||||
						{%- if entity.isActive -%}
 | 
			
		||||
							<i class="fa fa-check-square-o"></i>
 | 
			
		||||
						{%- else -%}
 | 
			
		||||
							<i class="fa fa-square-o"></i>
 | 
			
		||||
						{%- endif -%}
 | 
			
		||||
					</td>
 | 
			
		||||
					<td>
 | 
			
		||||
						<ul class="record_actions">
 | 
			
		||||
							<li>
 | 
			
		||||
								<a href="{{ path('chill_crud_charge_kind_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
 | 
			
		||||
							</li>
 | 
			
		||||
						</ul>
 | 
			
		||||
					</td>
 | 
			
		||||
				</tr>
 | 
			
		||||
			{% endfor %}
 | 
			
		||||
		</tbody>
 | 
			
		||||
	</table>
 | 
			
		||||
 | 
			
		||||
    {{ chill_pagination(paginator) }}
 | 
			
		||||
 | 
			
		||||
	<ul class="record_actions sticky-form-buttons">
 | 
			
		||||
		<li>
 | 
			
		||||
			<a href="{{ path('chill_crud_charge_kind_new') }}" class="btn btn-create">
 | 
			
		||||
				{{ 'admin.new.Create a new charge type'|trans }}
 | 
			
		||||
			</a>
 | 
			
		||||
		</li>
 | 
			
		||||
	</ul>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
 | 
			
		||||
 | 
			
		||||
{% block title %}
 | 
			
		||||
    {% include('@ChillMain/CRUD/_new_title.html.twig') %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block admin_content %}
 | 
			
		||||
    {% embed '@ChillMain/CRUD/_new_content.html.twig' %}
 | 
			
		||||
        {% block content_form_actions_save_and_show %}{% endblock %}
 | 
			
		||||
    {% endembed %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@@ -0,0 +1,12 @@
 | 
			
		||||
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
 | 
			
		||||
 | 
			
		||||
{% block title %}
 | 
			
		||||
    {% include('@ChillMain/CRUD/_edit_title.html.twig') %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block admin_content %}
 | 
			
		||||
    {% embed '@ChillMain/CRUD/_edit_content.html.twig' %}
 | 
			
		||||
        {% block content_form_actions_view %}{% endblock %}
 | 
			
		||||
        {% block content_form_actions_save_and_show %}{% endblock %}
 | 
			
		||||
    {% endembed %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@@ -0,0 +1,54 @@
 | 
			
		||||
{% extends '@ChillMain/Admin/layoutWithVerticalMenu.html.twig' %}
 | 
			
		||||
 | 
			
		||||
{% block title %}{{ 'admin.title.Resource Type List'|trans }}{% endblock title %}
 | 
			
		||||
 | 
			
		||||
{% block admin_content %}
 | 
			
		||||
 | 
			
		||||
    <h1>{{ 'admin.title.Resource Type List'|trans }}</h1>
 | 
			
		||||
 | 
			
		||||
	<table class="records_list table table-bordered border-dark">
 | 
			
		||||
		<thead>
 | 
			
		||||
			<tr>
 | 
			
		||||
                <th>{{ 'Ordering'|trans }}</th>
 | 
			
		||||
				<th>{{ 'Name'|trans }}</th>
 | 
			
		||||
				<th>{{ 'Active'|trans }}</th>
 | 
			
		||||
                <th> </th>
 | 
			
		||||
			</tr>
 | 
			
		||||
		</thead>
 | 
			
		||||
		<tbody>
 | 
			
		||||
			{% for entity in entities %}
 | 
			
		||||
				<tr>
 | 
			
		||||
                    <td>{{ entity.ordering }}</td>
 | 
			
		||||
                    <td>
 | 
			
		||||
                        {{ entity|chill_entity_render_box }}<br/>
 | 
			
		||||
                        <strong>{{ 'budget.admin.form.Resource_kind_key'|trans }} :</strong> <code>{{ entity.kind }}</code>
 | 
			
		||||
                    </td>
 | 
			
		||||
					<td style="text-align:center;">
 | 
			
		||||
						{%- if entity.isActive -%}
 | 
			
		||||
							<i class="fa fa-check-square-o"></i>
 | 
			
		||||
						{%- else -%}
 | 
			
		||||
							<i class="fa fa-square-o"></i>
 | 
			
		||||
						{%- endif -%}
 | 
			
		||||
					</td>
 | 
			
		||||
					<td>
 | 
			
		||||
						<ul class="record_actions">
 | 
			
		||||
							<li>
 | 
			
		||||
								<a href="{{ path('chill_crud_resource_kind_edit', { 'id': entity.id }) }}" class="btn btn-edit" title="{{ 'edit'|trans }}"></a>
 | 
			
		||||
							</li>
 | 
			
		||||
						</ul>
 | 
			
		||||
					</td>
 | 
			
		||||
				</tr>
 | 
			
		||||
			{% endfor %}
 | 
			
		||||
		</tbody>
 | 
			
		||||
	</table>
 | 
			
		||||
 | 
			
		||||
    {{ chill_pagination(paginator) }}
 | 
			
		||||
 | 
			
		||||
	<ul class="record_actions sticky-form-buttons">
 | 
			
		||||
		<li>
 | 
			
		||||
			<a href="{{ path('chill_crud_resource_kind_new') }}" class="btn btn-create">
 | 
			
		||||
				{{ 'admin.new.Create a new resource type'|trans }}
 | 
			
		||||
			</a>
 | 
			
		||||
		</li>
 | 
			
		||||
	</ul>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{% extends '@ChillMain/CRUD/Admin/index.html.twig' %}
 | 
			
		||||
 | 
			
		||||
{% block title %}
 | 
			
		||||
    {% include('@ChillMain/CRUD/_new_title.html.twig') %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block admin_content %}
 | 
			
		||||
    {% embed '@ChillMain/CRUD/_new_content.html.twig' %}
 | 
			
		||||
        {% block content_form_actions_save_and_show %}{% endblock %}
 | 
			
		||||
    {% endembed %}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@@ -0,0 +1,14 @@
 | 
			
		||||
{% extends "@ChillMain/Admin/layoutWithVerticalMenu.html.twig" %}
 | 
			
		||||
 | 
			
		||||
{% block vertical_menu_content %}
 | 
			
		||||
    {{ chill_menu('admin_budget', {
 | 
			
		||||
        'layout': '@ChillMain/Admin/menu_admin_section.html.twig',
 | 
			
		||||
    }) }}
 | 
			
		||||
{% endblock %}
 | 
			
		||||
 | 
			
		||||
{% block layout_wvm_content %}
 | 
			
		||||
    {% block admin_content %}
 | 
			
		||||
        <!-- block content empty -->
 | 
			
		||||
        <h1>{{ 'admin.title.Budget configuration'|trans }}</h1>
 | 
			
		||||
    {% endblock %}
 | 
			
		||||
{% endblock  %}
 | 
			
		||||
@@ -16,7 +16,11 @@
 | 
			
		||||
            <td class="column-wide el-type">
 | 
			
		||||
                <span class="badge-title">
 | 
			
		||||
                    <span class="title_label title_label_{{ family }}"></span>
 | 
			
		||||
                    <span class="title_action">{{ f.type|budget_element_type_display(family) }}<span>
 | 
			
		||||
                    {% if f.isResource %}
 | 
			
		||||
                        <span class="title_action">{{ f.resource.name|localize_translatable_string }}<span>
 | 
			
		||||
                    {% else %}
 | 
			
		||||
                        <span class="title_action">{{ f.charge.name|localize_translatable_string }}<span>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                </span>
 | 
			
		||||
            </td>
 | 
			
		||||
            <td class="column-small">{{ f.amount|format_currency('EUR') }}</td>
 | 
			
		||||
 
 | 
			
		||||
@@ -3,13 +3,13 @@
 | 
			
		||||
    {% set indexPage = 'chill_budget_elements_index' %}
 | 
			
		||||
    {% set activeRouteKey = '' %}
 | 
			
		||||
    {% set person = element.person %}
 | 
			
		||||
    {% set confirm_question = 'Are you sure you want to remove the charge "%type%" associated to "%name%" ?'|trans({ '%name%' : person.firstname ~ ' ' ~ person.lastname, '%type%': element.type|budget_element_type_display('charge') } ) %}
 | 
			
		||||
    {% set confirm_question = 'Are you sure you want to remove the charge "%type%" associated to "%name%" ?'|trans({ '%name%' : person.firstname ~ ' ' ~ person.lastname, '%type%': element.charge.getName | localize_translatable_string } ) %}
 | 
			
		||||
{% else %}
 | 
			
		||||
    {% set template = '@ChillPerson/Household/layout.html.twig' %}
 | 
			
		||||
    {% set indexPage = 'chill_budget_elements_household_index' %}
 | 
			
		||||
    {% set activeRouteKey = '' %}
 | 
			
		||||
    {% set household = element.household %}
 | 
			
		||||
    {% set confirm_question = 'Are you sure you want to remove the charge "%type%" associated to household "%household%" ?'|trans({ '%household%' : household.id, '%type%': element.type|budget_element_type_display('charge') } ) %}
 | 
			
		||||
    {% set confirm_question = 'Are you sure you want to remove the charge "%type%" associated to household "%household%" ?'|trans({ '%household%' : household.id, '%type%': element.charge.getName | localize_translatable_string } ) %}
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
{% extends template %}
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
 | 
			
		||||
{{ form_start(form) }}
 | 
			
		||||
 | 
			
		||||
{{ form_row(form.type) }}
 | 
			
		||||
{{ form_row(form.charge) }}
 | 
			
		||||
{{ form_row(form.amount) }}
 | 
			
		||||
{{ form_row(form.help) }}
 | 
			
		||||
{{ form_row(form.comment) }}
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
 | 
			
		||||
{{ form_start(form) }}
 | 
			
		||||
 | 
			
		||||
{{ form_row(form.type) }}
 | 
			
		||||
{{ form_row(form.charge) }}
 | 
			
		||||
{{ form_row(form.amount) }}
 | 
			
		||||
{{ form_row(form.help) }}
 | 
			
		||||
{{ form_row(form.comment) }}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@
 | 
			
		||||
            <div class="item-row">
 | 
			
		||||
                <h2 class="badge-title">
 | 
			
		||||
                    <span class="title_label title_label_charge"></span>
 | 
			
		||||
                    <span class="title_action">{{ element.type|budget_element_type_display('charge') }}</span>
 | 
			
		||||
                    <span class="title_action">{{ element.charge.getName | localize_translatable_string }}</span>
 | 
			
		||||
                </h2>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="item-row separator">
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
<span class="chill-entity">{{ entity.name|localize_translatable_string }}</span>
 | 
			
		||||
@@ -3,13 +3,13 @@
 | 
			
		||||
    {% set indexPage = 'chill_budget_elements_index' %}
 | 
			
		||||
    {% set activeRouteKey = '' %}
 | 
			
		||||
    {% set person = element.person %}
 | 
			
		||||
    {% set confirm_question = 'Are you sure you want to remove the ressource "%type%" associated to "%name%" ?'|trans({ '%name%' : person.firstname ~ ' ' ~ person.lastname, '%type%': element.type|budget_element_type_display('resource') } ) %}
 | 
			
		||||
    {% set confirm_question = 'Are you sure you want to remove the ressource "%type%" associated to "%name%" ?'|trans({ '%name%' : person.firstname ~ ' ' ~ person.lastname, '%type%': element.resource.getName | localize_translatable_string } ) %}
 | 
			
		||||
{% else %}
 | 
			
		||||
    {% set template = '@ChillPerson/Household/layout.html.twig' %}
 | 
			
		||||
    {% set indexPage = 'chill_budget_elements_household_index' %}
 | 
			
		||||
    {% set activeRouteKey = '' %}
 | 
			
		||||
    {% set household = element.household %}
 | 
			
		||||
    {% set confirm_question = 'Are you sure you want to remove the ressource "%type%" associated to household "%household%" ?'|trans({ '%household%' : household.id, '%type%': element.type|budget_element_type_display('resource') } ) %}
 | 
			
		||||
    {% set confirm_question = 'Are you sure you want to remove the ressource "%type%" associated to household "%household%" ?'|trans({ '%household%' : household.id, '%type%': element.resource.getName | localize_translatable_string} ) %}
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
{% extends template %}
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@
 | 
			
		||||
 | 
			
		||||
{{ form_start(form) }}
 | 
			
		||||
 | 
			
		||||
{{ form_row(form.type) }}
 | 
			
		||||
{{ form_row(form.resource) }}
 | 
			
		||||
{{ form_row(form.amount) }}
 | 
			
		||||
{{ form_row(form.comment) }}
 | 
			
		||||
{{ form_row(form.startDate) }}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,8 +22,7 @@
 | 
			
		||||
<h1>{{ title }}</h1>
 | 
			
		||||
 | 
			
		||||
{{ form_start(form) }}
 | 
			
		||||
 | 
			
		||||
{{ form_row(form.type) }}
 | 
			
		||||
{{ form_row(form.resource) }}
 | 
			
		||||
{{ form_row(form.amount) }}
 | 
			
		||||
{{ form_row(form.comment) }}
 | 
			
		||||
{{ form_row(form.startDate) }}
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@
 | 
			
		||||
            <div class="item-row">
 | 
			
		||||
                <h2 class="badge-title">
 | 
			
		||||
                    <span class="title_label title_label_resource"></span>
 | 
			
		||||
                    <span class="title_action title_action">{{ element.type|budget_element_type_display('resource') }}</span>
 | 
			
		||||
                    <span class="title_action title_action">{{ element.resource.getName | localize_translatable_string }}</span>
 | 
			
		||||
                </h2>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="item-row separator">
 | 
			
		||||
 
 | 
			
		||||
@@ -11,45 +11,52 @@ declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Service\Summary;
 | 
			
		||||
 | 
			
		||||
use Chill\BudgetBundle\Config\ConfigRepository;
 | 
			
		||||
use Chill\BudgetBundle\Entity\ChargeKind;
 | 
			
		||||
use Chill\BudgetBundle\Entity\ResourceKind;
 | 
			
		||||
use Chill\BudgetBundle\Repository\ChargeKindRepository;
 | 
			
		||||
use Chill\BudgetBundle\Repository\ChargeKindRepositoryInterface;
 | 
			
		||||
use Chill\BudgetBundle\Repository\ResourceKindRepository;
 | 
			
		||||
use Chill\BudgetBundle\Repository\ResourceKindRepositoryInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Chill\PersonBundle\Entity\Household\Household;
 | 
			
		||||
use Chill\PersonBundle\Entity\Person;
 | 
			
		||||
use Doctrine\ORM\EntityManagerInterface;
 | 
			
		||||
use Doctrine\ORM\Query\ResultSetMapping;
 | 
			
		||||
use LogicException;
 | 
			
		||||
use RuntimeException;
 | 
			
		||||
use function count;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Helps to find a summary of the budget: the sum of resources and charges.
 | 
			
		||||
 */
 | 
			
		||||
class SummaryBudget implements SummaryBudgetInterface
 | 
			
		||||
final class SummaryBudget implements SummaryBudgetInterface
 | 
			
		||||
{
 | 
			
		||||
    private const QUERY_CHARGE_BY_HOUSEHOLD = 'select SUM(amount) AS sum, string_agg(comment, \'|\') AS comment, type FROM chill_budget.charge WHERE (person_id IN (_ids_) OR household_id = ?) AND NOW() BETWEEN startdate AND COALESCE(enddate, \'infinity\'::timestamp) GROUP BY type';
 | 
			
		||||
    private const QUERY_CHARGE_BY_HOUSEHOLD = 'select SUM(amount) AS sum, string_agg(comment, \'|\') AS comment, charge_id AS kind_id FROM chill_budget.charge WHERE (person_id IN (_ids_) OR household_id = ?) AND NOW() BETWEEN startdate AND COALESCE(enddate, \'infinity\'::timestamp) GROUP BY charge_id';
 | 
			
		||||
 | 
			
		||||
    private const QUERY_CHARGE_BY_PERSON = 'select SUM(amount) AS sum, string_agg(comment, \'|\') AS comment, type FROM chill_budget.charge WHERE person_id = ? AND NOW() BETWEEN startdate AND COALESCE(enddate, \'infinity\'::timestamp) GROUP BY type';
 | 
			
		||||
    private const QUERY_CHARGE_BY_PERSON = 'select SUM(amount) AS sum, string_agg(comment, \'|\') AS comment, charge_id AS kind_id FROM chill_budget.charge WHERE person_id = ? AND NOW() BETWEEN startdate AND COALESCE(enddate, \'infinity\'::timestamp) GROUP BY charge_id';
 | 
			
		||||
 | 
			
		||||
    private const QUERY_RESOURCE_BY_HOUSEHOLD = 'select SUM(amount) AS sum, string_agg(comment, \'|\') AS comment, type FROM chill_budget.resource WHERE (person_id IN (_ids_) OR household_id = ?) AND NOW() BETWEEN startdate AND COALESCE(enddate, \'infinity\'::timestamp) GROUP BY type';
 | 
			
		||||
    private const QUERY_RESOURCE_BY_HOUSEHOLD = 'select SUM(amount) AS sum, string_agg(comment, \'|\') AS comment, resource_id AS kind_id FROM chill_budget.resource WHERE (person_id IN (_ids_) OR household_id = ?) AND NOW() BETWEEN startdate AND COALESCE(enddate, \'infinity\'::timestamp) GROUP BY resource_id';
 | 
			
		||||
 | 
			
		||||
    private const QUERY_RESOURCE_BY_PERSON = 'select SUM(amount) AS sum, string_agg(comment, \'|\') AS comment, type FROM chill_budget.resource WHERE person_id = ? AND NOW() BETWEEN startdate AND COALESCE(enddate, \'infinity\'::timestamp) GROUP BY type';
 | 
			
		||||
    private const QUERY_RESOURCE_BY_PERSON = 'select SUM(amount) AS sum, string_agg(comment, \'|\') AS comment, resource_id AS kind_id FROM chill_budget.resource WHERE person_id = ? AND NOW() BETWEEN startdate AND COALESCE(enddate, \'infinity\'::timestamp) GROUP BY resource_id';
 | 
			
		||||
 | 
			
		||||
    private array $chargeLabels;
 | 
			
		||||
 | 
			
		||||
    private ConfigRepository $configRepository;
 | 
			
		||||
    private ChargeKindRepositoryInterface $chargeKindRepository;
 | 
			
		||||
 | 
			
		||||
    private EntityManagerInterface $em;
 | 
			
		||||
 | 
			
		||||
    private array $resourcesLabels;
 | 
			
		||||
    private ResourceKindRepositoryInterface $resourceKindRepository;
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(EntityManagerInterface $em, ConfigRepository $configRepository, TranslatableStringHelperInterface $translatableStringHelper)
 | 
			
		||||
    {
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        EntityManagerInterface $em,
 | 
			
		||||
        TranslatableStringHelperInterface $translatableStringHelper,
 | 
			
		||||
        ResourceKindRepositoryInterface $resourceKindRepository,
 | 
			
		||||
        ChargeKindRepositoryInterface $chargeKindRepository
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->em = $em;
 | 
			
		||||
        $this->configRepository = $configRepository;
 | 
			
		||||
        $this->chargeLabels = $configRepository->getChargesLabels();
 | 
			
		||||
        $this->resourcesLabels = $configRepository->getResourcesLabels();
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
        $this->resourceKindRepository = $resourceKindRepository;
 | 
			
		||||
        $this->chargeKindRepository = $chargeKindRepository;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getSummaryForHousehold(?Household $household): array
 | 
			
		||||
@@ -112,7 +119,7 @@ class SummaryBudget implements SummaryBudgetInterface
 | 
			
		||||
        $rsm = new ResultSetMapping();
 | 
			
		||||
        $rsm
 | 
			
		||||
            ->addScalarResult('sum', 'sum')
 | 
			
		||||
            ->addScalarResult('type', 'type')
 | 
			
		||||
            ->addScalarResult('kind_id', 'kind_id')
 | 
			
		||||
            ->addScalarResult('comment', 'comment');
 | 
			
		||||
 | 
			
		||||
        return $rsm;
 | 
			
		||||
@@ -120,51 +127,62 @@ class SummaryBudget implements SummaryBudgetInterface
 | 
			
		||||
 | 
			
		||||
    private function getEmptyChargeArray(): array
 | 
			
		||||
    {
 | 
			
		||||
        $keys = $this->configRepository->getChargesKeys();
 | 
			
		||||
        $labels = $this->chargeLabels;
 | 
			
		||||
        $keys = array_map(static fn (ChargeKind $kind) => $kind->getKind(), $this->chargeKindRepository->findAll());
 | 
			
		||||
 | 
			
		||||
        return array_combine($keys, array_map(function ($i) use ($labels) {
 | 
			
		||||
            return ['sum' => 0.0, 'label' => $this->translatableStringHelper->localize($labels[$i]), 'comment' => ''];
 | 
			
		||||
        return array_combine($keys, array_map(function ($kind) {
 | 
			
		||||
            return ['sum' => 0.0, 'label' => $this->translatableStringHelper->localize($this->chargeKindRepository->findOneByKind($kind)->getName()), 'comment' => ''];
 | 
			
		||||
        }, $keys));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function getEmptyResourceArray(): array
 | 
			
		||||
    {
 | 
			
		||||
        $keys = $this->configRepository->getResourcesKeys();
 | 
			
		||||
        $labels = $this->resourcesLabels;
 | 
			
		||||
        $keys = array_map(static fn (ResourceKind $kind) => $kind->getKind(), $this->resourceKindRepository->findAll());
 | 
			
		||||
 | 
			
		||||
        return array_combine($keys, array_map(function ($i) use ($labels) {
 | 
			
		||||
            return ['sum' => 0.0, 'label' => $this->translatableStringHelper->localize($labels[$i]), 'comment' => ''];
 | 
			
		||||
        return array_combine($keys, array_map(function ($kind) {
 | 
			
		||||
            return ['sum' => 0.0, 'label' => $this->translatableStringHelper->localize($this->resourceKindRepository->findOneByKind($kind)->getName()), 'comment' => ''];
 | 
			
		||||
        }, $keys));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function rowToArray(array $rows, string $kind): array
 | 
			
		||||
    {
 | 
			
		||||
        $result = [];
 | 
			
		||||
 | 
			
		||||
        switch ($kind) {
 | 
			
		||||
            case 'charge':
 | 
			
		||||
                $label = $this->chargeLabels;
 | 
			
		||||
                foreach ($rows as $row) {
 | 
			
		||||
                    $chargeKind = $this->chargeKindRepository->find($row['kind_id']);
 | 
			
		||||
 | 
			
		||||
                break;
 | 
			
		||||
                    if (null === $chargeKind) {
 | 
			
		||||
                        throw new RuntimeException('charge kind not found: ' . $row['kind_id']);
 | 
			
		||||
                    }
 | 
			
		||||
                    $result[$chargeKind->getKind()] = [
 | 
			
		||||
                        'sum' => (float) $row['sum'],
 | 
			
		||||
                        'label' => $this->translatableStringHelper->localize($chargeKind->getName()),
 | 
			
		||||
                        'comment' => (string) $row['comment'],
 | 
			
		||||
                    ];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return $result;
 | 
			
		||||
 | 
			
		||||
            case 'resource':
 | 
			
		||||
                $label = $this->resourcesLabels;
 | 
			
		||||
                foreach ($rows as $row) {
 | 
			
		||||
                    $resourceKind = $this->resourceKindRepository->find($row['kind_id']);
 | 
			
		||||
 | 
			
		||||
                break;
 | 
			
		||||
                    if (null === $resourceKind) {
 | 
			
		||||
                        throw new RuntimeException('charge kind not found: ' . $row['kind_id']);
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    $result[$resourceKind->getKind()] = [
 | 
			
		||||
                        'sum' => (float) $row['sum'],
 | 
			
		||||
                        'label' => $this->translatableStringHelper->localize($resourceKind->getName()),
 | 
			
		||||
                        'comment' => (string) $row['comment'],
 | 
			
		||||
                    ];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return $result;
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
                throw new LogicException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $result = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($rows as $row) {
 | 
			
		||||
            $result[$row['type']] = [
 | 
			
		||||
                'sum' => (float) $row['sum'],
 | 
			
		||||
                'label' => $this->translatableStringHelper->localize($label[$row['type']]),
 | 
			
		||||
                'comment' => (string) $row['comment'],
 | 
			
		||||
            ];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $result;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,55 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Templating;
 | 
			
		||||
 | 
			
		||||
use Chill\BudgetBundle\Entity\ChargeKind;
 | 
			
		||||
use Chill\BudgetBundle\Entity\ResourceKind;
 | 
			
		||||
use Chill\MainBundle\Templating\Entity\ChillEntityRenderInterface;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
 | 
			
		||||
use Symfony\Component\Templating\EngineInterface;
 | 
			
		||||
 | 
			
		||||
final class BudgetElementTypeRender implements ChillEntityRenderInterface
 | 
			
		||||
{
 | 
			
		||||
    private EngineInterface $engine;
 | 
			
		||||
 | 
			
		||||
    private TranslatableStringHelperInterface $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(TranslatableStringHelperInterface $translatableStringHelper, EngineInterface $engine)
 | 
			
		||||
    {
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
        $this->engine = $engine;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function renderBox($entity, array $options): string
 | 
			
		||||
    {
 | 
			
		||||
        return $this->engine->render('@ChillBudget/Entity/budget_element_type.html.twig', [
 | 
			
		||||
            'entity' => $entity,
 | 
			
		||||
            'options' => $options,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function renderString($entity, array $options): string
 | 
			
		||||
    {
 | 
			
		||||
        $title = '';
 | 
			
		||||
 | 
			
		||||
        if (null !== $entity->getName()) {
 | 
			
		||||
            return $this->translatableStringHelper->localize($entity->getName());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $title;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function supports($entity, array $options): bool
 | 
			
		||||
    {
 | 
			
		||||
        return $entity instanceof ChargeKind || $entity instanceof ResourceKind;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,65 +0,0 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
declare(strict_types=1);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
namespace Chill\BudgetBundle\Templating;
 | 
			
		||||
 | 
			
		||||
use Chill\BudgetBundle\Config\ConfigRepository;
 | 
			
		||||
use Chill\MainBundle\Templating\TranslatableStringHelper;
 | 
			
		||||
use Twig\Extension\AbstractExtension;
 | 
			
		||||
use Twig\TwigFilter;
 | 
			
		||||
use UnexpectedValueException;
 | 
			
		||||
 | 
			
		||||
class Twig extends AbstractExtension
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @var ConfigRepository
 | 
			
		||||
     */
 | 
			
		||||
    protected $configRepository;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var TranslatableStringHelper
 | 
			
		||||
     */
 | 
			
		||||
    protected $translatableStringHelper;
 | 
			
		||||
 | 
			
		||||
    public function __construct(
 | 
			
		||||
        ConfigRepository $configRepository,
 | 
			
		||||
        TranslatableStringHelper $translatableStringHelper
 | 
			
		||||
    ) {
 | 
			
		||||
        $this->configRepository = $configRepository;
 | 
			
		||||
        $this->translatableStringHelper = $translatableStringHelper;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function displayLink($link, $family)
 | 
			
		||||
    {
 | 
			
		||||
        switch ($family) {
 | 
			
		||||
            case 'resource':
 | 
			
		||||
                return $this->translatableStringHelper->localize(
 | 
			
		||||
                    $this->configRepository->getResourcesLabels()[$link]
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
            case 'charge':
 | 
			
		||||
                return $this->translatableStringHelper->localize(
 | 
			
		||||
                    $this->configRepository->getChargesLabels()[$link]
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
            default:
 | 
			
		||||
                throw new UnexpectedValueException("This family of element: {$family} is not "
 | 
			
		||||
                    . "supported. Supported families are 'resource', 'charge'");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function getFilters()
 | 
			
		||||
    {
 | 
			
		||||
        return [
 | 
			
		||||
            new TwigFilter('budget_element_type_display', [$this, 'displayLink'], ['is_safe' => ['html']]),
 | 
			
		||||
        ];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user