mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Merge remote-tracking branch 'origin/master' into issue706_cc_in_workflow-2
This commit is contained in:
commit
0335986326
@ -69,7 +69,7 @@ phpstan_tests:
|
|||||||
stage: Tests
|
stage: Tests
|
||||||
image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82
|
image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82
|
||||||
script:
|
script:
|
||||||
- bin/phpstan
|
- bin/phpstan analyze --memory-limit=2G
|
||||||
cache:
|
cache:
|
||||||
paths:
|
paths:
|
||||||
- .cache/
|
- .cache/
|
||||||
@ -79,21 +79,37 @@ phpstan_tests:
|
|||||||
- bin
|
- bin
|
||||||
- tests/app/vendor/
|
- tests/app/vendor/
|
||||||
|
|
||||||
psalm_tests:
|
rector_tests:
|
||||||
stage: Tests
|
stage: Tests
|
||||||
image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82
|
image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82
|
||||||
script:
|
script:
|
||||||
- bin/psalm
|
- bin/rector --dry-run
|
||||||
allow_failure: true
|
cache:
|
||||||
|
paths:
|
||||||
|
- .cache/
|
||||||
artifacts:
|
artifacts:
|
||||||
expire_in: 30 min
|
expire_in: 30 min
|
||||||
paths:
|
paths:
|
||||||
- bin
|
- bin
|
||||||
- tests/app/vendor/
|
- tests/app/vendor/
|
||||||
|
|
||||||
|
# psalm_tests:
|
||||||
|
# stage: Tests
|
||||||
|
# image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82
|
||||||
|
# script:
|
||||||
|
# - bin/psalm
|
||||||
|
# allow_failure: true
|
||||||
|
# artifacts:
|
||||||
|
# expire_in: 30 min
|
||||||
|
# paths:
|
||||||
|
# - bin
|
||||||
|
# - tests/app/vendor/
|
||||||
|
|
||||||
unit_tests:
|
unit_tests:
|
||||||
stage: Tests
|
stage: Tests
|
||||||
image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82
|
image: gitea.champs-libres.be/chill-project/chill-skeleton-basic/base-image:php82
|
||||||
|
# until we fix testes
|
||||||
|
allow_failure: true
|
||||||
script:
|
script:
|
||||||
- php tests/app/bin/console doctrine:migrations:migrate -n
|
- php tests/app/bin/console doctrine:migrations:migrate -n
|
||||||
- php -d memory_limit=2G tests/app/bin/console cache:clear --env=dev
|
- php -d memory_limit=2G tests/app/bin/console cache:clear --env=dev
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
"phpunit/phpunit": ">= 7.5",
|
"phpunit/phpunit": ">= 7.5",
|
||||||
"psalm/plugin-phpunit": "^0.18.4",
|
"psalm/plugin-phpunit": "^0.18.4",
|
||||||
"psalm/plugin-symfony": "^4.0.2",
|
"psalm/plugin-symfony": "^4.0.2",
|
||||||
|
"rector/rector": "^0.15.23",
|
||||||
"symfony/debug-bundle": "^5.1",
|
"symfony/debug-bundle": "^5.1",
|
||||||
"symfony/dotenv": "^4.4",
|
"symfony/dotenv": "^4.4",
|
||||||
"symfony/maker-bundle": "^1.20",
|
"symfony/maker-bundle": "^1.20",
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
"@fullcalendar/timegrid": "^6.1.4",
|
"@fullcalendar/timegrid": "^6.1.4",
|
||||||
"@fullcalendar/vue3": "^6.1.4",
|
"@fullcalendar/vue3": "^6.1.4",
|
||||||
"@popperjs/core": "^2.9.2",
|
"@popperjs/core": "^2.9.2",
|
||||||
|
"@types/leaflet": "^1.9.3",
|
||||||
"dropzone": "^5.7.6",
|
"dropzone": "^5.7.6",
|
||||||
"es6-promise": "^4.2.8",
|
"es6-promise": "^4.2.8",
|
||||||
"leaflet": "^1.7.1",
|
"leaflet": "^1.7.1",
|
||||||
|
@ -442,11 +442,6 @@ parameters:
|
|||||||
count: 2
|
count: 2
|
||||||
path: src/Bundle/ChillMainBundle/Workflow/Validator/StepDestValidValidator.php
|
path: src/Bundle/ChillMainBundle/Workflow/Validator/StepDestValidValidator.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Return type \\(int\\|void\\|null\\) of method Chill\\\\PersonBundle\\\\Command\\\\ImportPeopleFromCSVCommand\\:\\:execute\\(\\) should be covariant with return type \\(int\\) of method Symfony\\\\Component\\\\Console\\\\Command\\\\Command\\:\\:execute\\(\\)$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Parameter \\#3 \\$query \\(Doctrine\\\\ORM\\\\QueryBuilder\\) of method Chill\\\\PersonBundle\\\\Controller\\\\HouseholdCompositionTypeApiController\\:\\:customizeQuery\\(\\) should be contravariant with parameter \\$query \\(mixed\\) of method Chill\\\\MainBundle\\\\CRUD\\\\Controller\\\\AbstractCRUDController\\:\\:customizeQuery\\(\\)$#"
|
message: "#^Parameter \\#3 \\$query \\(Doctrine\\\\ORM\\\\QueryBuilder\\) of method Chill\\\\PersonBundle\\\\Controller\\\\HouseholdCompositionTypeApiController\\:\\:customizeQuery\\(\\) should be contravariant with parameter \\$query \\(mixed\\) of method Chill\\\\MainBundle\\\\CRUD\\\\Controller\\\\AbstractCRUDController\\:\\:customizeQuery\\(\\)$#"
|
||||||
count: 1
|
count: 1
|
||||||
@ -788,16 +783,6 @@ parameters:
|
|||||||
count: 1
|
count: 1
|
||||||
path: src/Bundle/ChillThirdPartyBundle/Security/Voter/ThirdPartyVoter.php
|
path: src/Bundle/ChillThirdPartyBundle/Security/Voter/ThirdPartyVoter.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#1 \\$thirdParty \\(Chill\\\\ThirdPartyBundle\\\\Entity\\\\ThirdParty\\) of method Chill\\\\ThirdPartyBundle\\\\Serializer\\\\Normalizer\\\\ThirdPartyNormalizer\\:\\:normalize\\(\\) should be contravariant with parameter \\$object \\(mixed\\) of method Symfony\\\\Component\\\\Serializer\\\\Normalizer\\\\NormalizerInterface\\:\\:normalize\\(\\)$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#2 \\$format \\(string\\) of method Chill\\\\ThirdPartyBundle\\\\Serializer\\\\Normalizer\\\\ThirdPartyNormalizer\\:\\:supportsNormalization\\(\\) should be contravariant with parameter \\$format \\(string\\|null\\) of method Symfony\\\\Component\\\\Serializer\\\\Normalizer\\\\NormalizerInterface\\:\\:supportsNormalization\\(\\)$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillThirdPartyBundle/Serializer/Normalizer/ThirdPartyNormalizer.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Parameter \\#1 \\$document \\(Chill\\\\DocStoreBundle\\\\Entity\\\\StoredObject\\) of method Chill\\\\WopiBundle\\\\Service\\\\Wopi\\\\ChillDocumentManager\\:\\:getBasename\\(\\) should be contravariant with parameter \\$document \\(ChampsLibres\\\\WopiLib\\\\Contract\\\\Entity\\\\Document\\) of method ChampsLibres\\\\WopiLib\\\\Contract\\\\Service\\\\DocumentManagerInterface\\:\\:getBasename\\(\\)$#"
|
message: "#^Parameter \\#1 \\$document \\(Chill\\\\DocStoreBundle\\\\Entity\\\\StoredObject\\) of method Chill\\\\WopiBundle\\\\Service\\\\Wopi\\\\ChillDocumentManager\\:\\:getBasename\\(\\) should be contravariant with parameter \\$document \\(ChampsLibres\\\\WopiLib\\\\Contract\\\\Entity\\\\Document\\) of method ChampsLibres\\\\WopiLib\\\\Contract\\\\Service\\\\DocumentManagerInterface\\:\\:getBasename\\(\\)$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
@ -3026,111 +3026,6 @@ parameters:
|
|||||||
count: 2
|
count: 2
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php
|
path: src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Access to an undefined property Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:\\:\\$force\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Access to an undefined property Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:\\:\\$headers\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Access to an undefined property Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:\\:\\$helperSet\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Access to an undefined property Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:\\:\\$input\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Access to an undefined property Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:\\:\\$output\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Access to an undefined property Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:\\:\\$person\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Access to an undefined property Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:\\:\\$rawHeaders\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Access to an undefined property Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:\\:\\$row\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Access to an undefined property Symfony\\\\Component\\\\EventDispatcher\\\\Event\\:\\:\\$skipPerson\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Call to an undefined method Doctrine\\\\Persistence\\\\ObjectManager\\:\\:createQuery\\(\\)\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Call to method buildForm\\(\\) on an unknown class Chill\\\\CustomFieldsBundle\\\\Service\\\\CustomFieldInterface\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Else branch is unreachable because previous condition is always true\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Elseif branch is unreachable because previous condition is always true\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Instanceof between \\*NEVER\\* and Symfony\\\\Component\\\\Form\\\\ChoiceList\\\\View\\\\ChoiceGroupView will always evaluate to false\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Instanceof between Symfony\\\\Component\\\\Form\\\\ChoiceList\\\\View\\\\ChoiceView and Symfony\\\\Component\\\\Form\\\\ChoiceList\\\\View\\\\ChoiceView will always evaluate to true\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method Chill\\\\PersonBundle\\\\Command\\\\ImportPeopleFromCSVCommand\\:\\:processTextType\\(\\) has invalid return type Chill\\\\PersonBundle\\\\Command\\\\type\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method Symfony\\\\Component\\\\Console\\\\Helper\\\\Table\\:\\:render\\(\\) invoked with 1 parameter, 0 required\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) invoked with 2 parameters, 1 required\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^PHPDoc tag @var above foreach loop does not specify variable name\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\$value of method Chill\\\\PersonBundle\\\\Command\\\\ImportPeopleFromCSVCommand\\:\\:processTextType\\(\\) has invalid type Chill\\\\PersonBundle\\\\Command\\\\type\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Strict comparison using \\=\\=\\= between false and false will always evaluate to true\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^PHPDoc tag @var for property Chill\\\\PersonBundle\\\\Command\\\\ImportSocialWorkMetadata\\:\\:\\$importer with type Psr\\\\Log\\\\LoggerInterface is not subtype of native type Chill\\\\PersonBundle\\\\Service\\\\Import\\\\ChillImporter\\.$#"
|
message: "#^PHPDoc tag @var for property Chill\\\\PersonBundle\\\\Command\\\\ImportSocialWorkMetadata\\:\\:\\$importer with type Psr\\\\Log\\\\LoggerInterface is not subtype of native type Chill\\\\PersonBundle\\\\Service\\\\Import\\\\ChillImporter\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
@ -425,21 +425,6 @@ parameters:
|
|||||||
count: 2
|
count: 2
|
||||||
path: src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php
|
path: src/Bundle/ChillPersonBundle/Actions/Remove/PersonMove.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#1 \\$mobilenumber of method Chill\\\\PersonBundle\\\\Entity\\\\Person\\:\\:setMobilenumber\\(\\) expects libphonenumber\\\\PhoneNumber\\|null, string given\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Parameter \\#1 \\$phonenumber of method Chill\\\\PersonBundle\\\\Entity\\\\Person\\:\\:setPhonenumber\\(\\) expects libphonenumber\\\\PhoneNumber\\|null, string given\\.$#"
|
|
||||||
count: 1
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#"
|
message: "#^Parameter \\#1 \\$event of method Symfony\\\\Contracts\\\\EventDispatcher\\\\EventDispatcherInterface\\:\\:dispatch\\(\\) expects object, string given\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
@ -310,11 +310,6 @@ parameters:
|
|||||||
count: 1
|
count: 1
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php
|
path: src/Bundle/ChillPersonBundle/Command/ChillPersonMoveCommand.php
|
||||||
|
|
||||||
-
|
|
||||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
|
||||||
count: 6
|
|
||||||
path: src/Bundle/ChillPersonBundle/Command/ImportPeopleFromCSVCommand.php
|
|
||||||
|
|
||||||
-
|
-
|
||||||
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
|
||||||
count: 1
|
count: 1
|
||||||
|
@ -3,7 +3,7 @@ parameters:
|
|||||||
paths:
|
paths:
|
||||||
- src/
|
- src/
|
||||||
tmpDir: .cache/
|
tmpDir: .cache/
|
||||||
reportUnmatchedIgnoredErrors: true
|
reportUnmatchedIgnoredErrors: false
|
||||||
excludePaths:
|
excludePaths:
|
||||||
- .php_cs*
|
- .php_cs*
|
||||||
- docs/
|
- docs/
|
||||||
|
25
rector.php
Normal file
25
rector.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
|
||||||
|
use Rector\Config\RectorConfig;
|
||||||
|
use Rector\Set\ValueObject\LevelSetList;
|
||||||
|
|
||||||
|
return static function (RectorConfig $rectorConfig): void {
|
||||||
|
$rectorConfig->paths([
|
||||||
|
__DIR__ . '/docs',
|
||||||
|
__DIR__ . '/src',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$rectorConfig->cacheClass(\Rector\Caching\ValueObject\Storage\FileCacheStorage::class);
|
||||||
|
$rectorConfig->cacheDirectory(__DIR__.'/.cache/rector');
|
||||||
|
|
||||||
|
// register a single rule
|
||||||
|
$rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class);
|
||||||
|
|
||||||
|
// define sets of rules
|
||||||
|
// $rectorConfig->sets([
|
||||||
|
// LevelSetList::UP_TO_PHP_74
|
||||||
|
// ]);
|
||||||
|
};
|
@ -195,7 +195,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
|||||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
|
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\User")
|
||||||
* @Groups({"docgen:read"})
|
* @Groups({"docgen:read"})
|
||||||
*/
|
*/
|
||||||
private User $user;
|
private ?User $user;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\ManyToMany(targetEntity="Chill\MainBundle\Entity\User")
|
* @ORM\ManyToMany(targetEntity="Chill\MainBundle\Entity\User")
|
||||||
@ -494,7 +494,7 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
|||||||
return $this->activityType;
|
return $this->activityType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getUser(): User
|
public function getUser(): ?User
|
||||||
{
|
{
|
||||||
return $this->user;
|
return $this->user;
|
||||||
}
|
}
|
||||||
@ -681,14 +681,14 @@ class Activity implements AccompanyingPeriodLinkedWithSocialIssuesEntityInterfac
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUser(UserInterface $user): self
|
public function setUser(?User $user): self
|
||||||
{
|
{
|
||||||
$this->user = $user;
|
$this->user = $user;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUsers(?Collection $users): self
|
public function setUsers(Collection $users): self
|
||||||
{
|
{
|
||||||
$this->users = $users;
|
$this->users = $users;
|
||||||
|
|
||||||
|
@ -20,13 +20,6 @@ use Symfony\Component\Form\FormBuilderInterface;
|
|||||||
|
|
||||||
class LocationFilter implements FilterInterface
|
class LocationFilter implements FilterInterface
|
||||||
{
|
{
|
||||||
private TranslatableStringHelper $translatableStringHelper;
|
|
||||||
|
|
||||||
public function __construct(TranslatableStringHelper $translatableStringHelper)
|
|
||||||
{
|
|
||||||
$this->translatableStringHelper = $translatableStringHelper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function addRole(): ?string
|
public function addRole(): ?string
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
@ -225,6 +225,7 @@ class ActivityType extends AbstractType
|
|||||||
$builder->add('user', PickUserDynamicType::class, [
|
$builder->add('user', PickUserDynamicType::class, [
|
||||||
'label' => $activityType->getLabel('user'),
|
'label' => $activityType->getLabel('user'),
|
||||||
'required' => $activityType->isRequired('user'),
|
'required' => $activityType->isRequired('user'),
|
||||||
|
'multiple' => false,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ final class PersonMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
|
|
||||||
if ($this->authorizationChecker->isGranted(ActivityVoter::SEE, $person)) {
|
if ($this->authorizationChecker->isGranted(ActivityVoter::SEE, $person)) {
|
||||||
$menu->addChild(
|
$menu->addChild(
|
||||||
$this->translator->trans('Activity list'),
|
$this->translator->trans('Activities'),
|
||||||
[
|
[
|
||||||
'route' => 'chill_activity_activity_list',
|
'route' => 'chill_activity_activity_list',
|
||||||
'routeParameters' => ['person_id' => $person->getId()],
|
'routeParameters' => ['person_id' => $person->getId()],
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if activity.user and t.userVisible %}
|
{% if activity.user is not null and t.userVisible %}
|
||||||
<div class="wl-row">
|
<div class="wl-row">
|
||||||
<div class="wl-col title"><h3>{{ 'Referrer'|trans }}</h3></div>
|
<div class="wl-col title"><h3>{{ 'Referrer'|trans }}</h3></div>
|
||||||
<div class="wl-col list">
|
<div class="wl-col list">
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
Maybe should we think about abstracting this file a bit more ? Moving it to PersonBundle ?
|
Maybe should we think about abstracting this file a bit more ? Moving it to PersonBundle ?
|
||||||
#}
|
#}
|
||||||
{% if context == 'calendar_accompanyingCourse' %}
|
{% if context == 'calendar_accompanyingCourse' or context == 'calendar_person' %}
|
||||||
{% import "@ChillCalendar/_invite.html.twig" as invite %}
|
{% import "@ChillCalendar/_invite.html.twig" as invite %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
@ -34,10 +34,12 @@
|
|||||||
|
|
||||||
<div class="item-row separator">
|
<div class="item-row separator">
|
||||||
<dl class="chill_view_data">
|
<dl class="chill_view_data">
|
||||||
|
{%- if entity.user is not null %}
|
||||||
<dt class="inline">{{ 'Referrer'|trans|capitalize }}</dt>
|
<dt class="inline">{{ 'Referrer'|trans|capitalize }}</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<span class="badge-user">{{ entity.user|chill_entity_render_box }}</span>
|
<span class="badge-user">{{ entity.user|chill_entity_render_box }}</span>
|
||||||
</dd>
|
</dd>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{%- if entity.scope -%}
|
{%- if entity.scope -%}
|
||||||
<dt class="inline">{{ 'Scope'|trans }}</dt>
|
<dt class="inline">{{ 'Scope'|trans }}</dt>
|
||||||
|
@ -147,6 +147,32 @@ class ActivityContext implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function contextGenerationDataDenormalize(DocGeneratorTemplate $template, $entity, array $data): array
|
||||||
|
{
|
||||||
|
$denormalized = [];
|
||||||
|
|
||||||
|
foreach (['mainPerson', 'person1', 'person2'] as $k) {
|
||||||
|
if (null !== ($id = ($data[$k] ?? null))) {
|
||||||
|
$denormalized[$k] = $this->personRepository->find($id);
|
||||||
|
} else {
|
||||||
|
$denormalized[$k] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $denormalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function contextGenerationDataNormalize(DocGeneratorTemplate $template, $entity, array $data): array
|
||||||
|
{
|
||||||
|
$normalized = [];
|
||||||
|
|
||||||
|
foreach (['mainPerson', 'person1', 'person2'] as $k) {
|
||||||
|
$normalized[$k] = null === $data[$k] ? null : $data[$k]->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $normalized;
|
||||||
|
}
|
||||||
|
|
||||||
public function getData(DocGeneratorTemplate $template, $entity, array $contextGenerationData = []): array
|
public function getData(DocGeneratorTemplate $template, $entity, array $contextGenerationData = []): array
|
||||||
{
|
{
|
||||||
if (!$entity instanceof Activity) {
|
if (!$entity instanceof Activity) {
|
||||||
@ -214,32 +240,6 @@ class ActivityContext implements
|
|||||||
return $options['mainPerson'] || $options['person1'] || $options['person2'];
|
return $options['mainPerson'] || $options['person1'] || $options['person2'];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function contextGenerationDataNormalize(DocGeneratorTemplate $template, $entity, array $data): array
|
|
||||||
{
|
|
||||||
$normalized = [];
|
|
||||||
|
|
||||||
foreach (['mainPerson', 'person1', 'person2'] as $k) {
|
|
||||||
$normalized[$k] = null === $data[$k] ? null : $data[$k]->getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $normalized;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function contextGenerationDataDenormalize(DocGeneratorTemplate $template, $entity, array $data): array
|
|
||||||
{
|
|
||||||
$denormalized = [];
|
|
||||||
|
|
||||||
foreach (['mainPerson', 'person1', 'person2'] as $k) {
|
|
||||||
if (null !== ($id = ($data[$k] ?? null))) {
|
|
||||||
$denormalized[$k] = $this->personRepository->find($id);
|
|
||||||
} else {
|
|
||||||
$denormalized[$k] = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $denormalized;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void
|
public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void
|
||||||
{
|
{
|
||||||
$storedObject->setTitle($this->translatableStringHelper->localize($template->getName()));
|
$storedObject->setTitle($this->translatableStringHelper->localize($template->getName()));
|
||||||
|
@ -34,10 +34,16 @@ use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
|||||||
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
|
use Chill\ThirdPartyBundle\Repository\ThirdPartyRepository;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use libphonenumber\PhoneNumber;
|
use libphonenumber\PhoneNumber;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||||
|
use function in_array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @implements DocGeneratorContextWithPublicFormInterface<AccompanyingPeriod>
|
||||||
|
* @implements DocGeneratorContextWithAdminFormInterface<AccompanyingPeriod>
|
||||||
|
*/
|
||||||
class ListActivitiesByAccompanyingPeriodContext implements
|
class ListActivitiesByAccompanyingPeriodContext implements
|
||||||
DocGeneratorContextWithAdminFormInterface,
|
DocGeneratorContextWithAdminFormInterface,
|
||||||
DocGeneratorContextWithPublicFormInterface
|
DocGeneratorContextWithPublicFormInterface
|
||||||
@ -69,7 +75,7 @@ class ListActivitiesByAccompanyingPeriodContext implements
|
|||||||
SocialIssueRepository $socialIssueRepository,
|
SocialIssueRepository $socialIssueRepository,
|
||||||
ThirdPartyRepository $thirdPartyRepository,
|
ThirdPartyRepository $thirdPartyRepository,
|
||||||
TranslatableStringHelperInterface $translatableStringHelper,
|
TranslatableStringHelperInterface $translatableStringHelper,
|
||||||
UserRepository $userRepository
|
UserRepository $userRepository,
|
||||||
) {
|
) {
|
||||||
$this->accompanyingPeriodContext = $accompanyingPeriodContext;
|
$this->accompanyingPeriodContext = $accompanyingPeriodContext;
|
||||||
$this->activityACLAwareRepository = $activityACLAwareRepository;
|
$this->activityACLAwareRepository = $activityACLAwareRepository;
|
||||||
@ -100,14 +106,86 @@ class ListActivitiesByAccompanyingPeriodContext implements
|
|||||||
public function buildPublicForm(FormBuilderInterface $builder, DocGeneratorTemplate $template, $entity): void
|
public function buildPublicForm(FormBuilderInterface $builder, DocGeneratorTemplate $template, $entity): void
|
||||||
{
|
{
|
||||||
$this->accompanyingPeriodContext->buildPublicForm($builder, $template, $entity);
|
$this->accompanyingPeriodContext->buildPublicForm($builder, $template, $entity);
|
||||||
|
|
||||||
|
$builder
|
||||||
|
->add('myActivitiesOnly', CheckboxType::class, [
|
||||||
|
'required' => false,
|
||||||
|
'label' => 'docgen.myActivitiesOnly',
|
||||||
|
])
|
||||||
|
->add('myWorksOnly', CheckboxType::class, [
|
||||||
|
'required' => false,
|
||||||
|
'label' => 'docgen.myWorksOnly',
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getData(DocGeneratorTemplate $template, $entity, array $contextGenerationData = []): array
|
public function contextGenerationDataDenormalize(DocGeneratorTemplate $template, $entity, array $data): array
|
||||||
|
{
|
||||||
|
|
||||||
|
$denormalized = $this->accompanyingPeriodContext->contextGenerationDataDenormalize($template, $entity, $data);
|
||||||
|
|
||||||
|
foreach (['myActivitiesOnly', 'myWorksOnly'] as $k) {
|
||||||
|
$denormalized[$k] = $data[$k];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $denormalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function contextGenerationDataNormalize(DocGeneratorTemplate $template, $entity, array $data): array
|
||||||
|
{
|
||||||
|
$normalized = $this->accompanyingPeriodContext->contextGenerationDataNormalize($template, $entity, $data);
|
||||||
|
|
||||||
|
foreach (['myActivitiesOnly', 'myWorksOnly'] as $k) {
|
||||||
|
$normalized[$k] = $data[$k] ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function filterActivitiesByUser(array $activities, User $user): array
|
||||||
|
{
|
||||||
|
return array_filter(
|
||||||
|
$activities,
|
||||||
|
function ($activity) use ($user) {
|
||||||
|
$activityUsernames = array_map(static function ($user) {
|
||||||
|
return $user['username'];
|
||||||
|
}, $activity['users'] ?? []);
|
||||||
|
return in_array($user->getUsername(), $activityUsernames, true);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function filterWorksByUser(array $works, User $user): array
|
||||||
|
{
|
||||||
|
return array_filter(
|
||||||
|
$works,
|
||||||
|
function ($work) use ($user) {
|
||||||
|
$workUsernames = array_map(static function ($user) {
|
||||||
|
return $user['username'];
|
||||||
|
}, $work['referrers'] ?? []);
|
||||||
|
|
||||||
|
return in_array($user->getUsername(), $workUsernames, true);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getData(DocGeneratorTemplate $template, object $entity, array $contextGenerationData = []): array
|
||||||
{
|
{
|
||||||
$data = $this->accompanyingPeriodContext->getData($template, $entity, $contextGenerationData);
|
$data = $this->accompanyingPeriodContext->getData($template, $entity, $contextGenerationData);
|
||||||
|
|
||||||
$data['activities'] = $this->getActivitiesSimplified($entity);
|
$activities = $this->getActivitiesSimplified($entity);
|
||||||
|
$myActivitiesOnly = $contextGenerationData['myActivitiesOnly'];
|
||||||
|
|
||||||
|
if ($myActivitiesOnly && isset($contextGenerationData['creator'])) {
|
||||||
|
$activities = $this->filterActivitiesByUser($activities, $contextGenerationData['creator']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$data['activities'] = $activities;
|
||||||
|
|
||||||
|
$myWorksOnly = $contextGenerationData['myWorksOnly'];
|
||||||
|
|
||||||
|
if ($myWorksOnly && isset($contextGenerationData['creator'])) {
|
||||||
|
$data['course']['works'] = $this->filterWorksByUser($data['course']['works'], $contextGenerationData['creator']);
|
||||||
|
}
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,17 +221,7 @@ class ListActivitiesByAccompanyingPeriodContext implements
|
|||||||
|
|
||||||
public function hasPublicForm(DocGeneratorTemplate $template, $entity): bool
|
public function hasPublicForm(DocGeneratorTemplate $template, $entity): bool
|
||||||
{
|
{
|
||||||
return $this->accompanyingPeriodContext->hasPublicForm($template, $entity);
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
public function contextGenerationDataNormalize(DocGeneratorTemplate $template, $entity, array $data): array
|
|
||||||
{
|
|
||||||
return $this->accompanyingPeriodContext->contextGenerationDataNormalize($template, $entity, $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function contextGenerationDataDenormalize(DocGeneratorTemplate $template, $entity, array $data): array
|
|
||||||
{
|
|
||||||
return $this->accompanyingPeriodContext->contextGenerationDataDenormalize($template, $entity, $data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void
|
public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void
|
||||||
|
@ -121,14 +121,14 @@ final class ActivityControllerTest extends WebTestCase
|
|||||||
$client->getResponse()->getStatusCode(),
|
$client->getResponse()->getStatusCode(),
|
||||||
'Unexpected HTTP status code for GET /activity/'
|
'Unexpected HTTP status code for GET /activity/'
|
||||||
);
|
);
|
||||||
$crawler = $client->click($crawler->selectLink('Ajouter une nouvelle activité')
|
$crawler = $client->click($crawler->selectLink('Ajouter un nouvel échange')
|
||||||
->link());
|
->link());
|
||||||
|
|
||||||
$reason1 = $this->getRandomActivityReason();
|
$reason1 = $this->getRandomActivityReason();
|
||||||
$reason2 = $this->getRandomActivityReason([$reason1->getId()]);
|
$reason2 = $this->getRandomActivityReason([$reason1->getId()]);
|
||||||
|
|
||||||
// Fill in the form and submit it
|
// Fill in the form and submit it
|
||||||
$form = $crawler->selectButton('Ajouter une nouvelle activité')->form([
|
$form = $crawler->selectButton('Ajouter un nouvel échange')->form([
|
||||||
'chill_activitybundle_activity' => [
|
'chill_activitybundle_activity' => [
|
||||||
'date' => '15-01-2015',
|
'date' => '15-01-2015',
|
||||||
'durationTime' => 600,
|
'durationTime' => 600,
|
||||||
@ -152,9 +152,9 @@ final class ActivityControllerTest extends WebTestCase
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Edit the entity
|
// Edit the entity
|
||||||
$crawler = $client->click($crawler->selectLink("Modifier l'activité")->link());
|
$crawler = $client->click($crawler->selectLink("Modifier l'échange")->link());
|
||||||
|
|
||||||
$form = $crawler->selectButton("Sauver l'activité")->form([
|
$form = $crawler->selectButton("Sauver l'échange")->form([
|
||||||
'chill_activitybundle_activity' => [
|
'chill_activitybundle_activity' => [
|
||||||
'date' => '25-01-2015',
|
'date' => '25-01-2015',
|
||||||
// 'remark' => 'Foo'
|
// 'remark' => 'Foo'
|
||||||
|
@ -1,41 +1,41 @@
|
|||||||
#general
|
#general
|
||||||
Show the activity: Voir l'activité
|
Show the activity: Voir l'échange
|
||||||
Edit the activity: Modifier l'activité
|
Edit the activity: Modifier l'échange
|
||||||
Activity: Activité
|
Activity: Échange
|
||||||
Duration time: Durée
|
Duration time: Durée
|
||||||
Duration Time: Durée
|
Duration Time: Durée
|
||||||
durationTime: durée
|
durationTime: durée
|
||||||
Travel time: Durée de déplacement
|
Travel time: Durée de déplacement
|
||||||
Attendee: Présence de la personne
|
Attendee: Présence de l'usager
|
||||||
attendee: présence de la personne
|
attendee: présence de l'usager
|
||||||
list_reasons: liste des sujets
|
list_reasons: liste des sujets
|
||||||
user_username: nom de l'utilisateur
|
user_username: nom de l'utilisateur
|
||||||
circle_name: nom du cercle
|
circle_name: nom du cercle
|
||||||
Remark: Commentaire
|
Remark: Commentaire
|
||||||
No comments: Aucun commentaire
|
No comments: Aucun commentaire
|
||||||
Add a new activity: Ajouter une nouvelle activité
|
Add a new activity: Ajouter une nouvel échange
|
||||||
Activity list: Liste des activités
|
Activity list: Liste des échanges
|
||||||
present: présent
|
present: présent
|
||||||
not present: absent
|
not present: absent
|
||||||
Delete: Supprimer
|
Delete: Supprimer
|
||||||
Update: Mettre à jour
|
Update: Mettre à jour
|
||||||
Update activity: Modifier l'activité
|
Update activity: Modifier l'échange
|
||||||
Scope: Cercle
|
Scope: Cercle
|
||||||
Activity data: Données de l'activité
|
Activity data: Données de l'échange
|
||||||
Activity location: Localisation de l'activité
|
Activity location: Localisation de l'échange
|
||||||
No reason associated: Aucun sujet
|
No reason associated: Aucun sujet
|
||||||
No social issues associated: Aucune problématique sociale
|
No social issues associated: Aucune problématique sociale
|
||||||
No social actions associated: Aucune action d'accompagnement
|
No social actions associated: Aucune action d'accompagnement
|
||||||
There isn't any activities.: Aucune activité enregistrée.
|
There isn't any activities.: Aucun échange enregistré.
|
||||||
type_name: type de l'activité
|
type_name: type de l'échange
|
||||||
person_firstname: prénom
|
person_firstname: prénom
|
||||||
person_lastname: nom de famille
|
person_lastname: nom de famille
|
||||||
person_id: identifiant de la personne
|
person_id: identifiant de l'usager
|
||||||
Type: Type
|
Type: Type
|
||||||
Invisible: Invisible
|
Invisible: Invisible
|
||||||
Optional: Optionnel
|
Optional: Optionnel
|
||||||
Required: Obligatoire
|
Required: Obligatoire
|
||||||
Persons: Personnes
|
Persons: Usagers
|
||||||
Users: Utilisateurs
|
Users: Utilisateurs
|
||||||
Emergency: Urgent
|
Emergency: Urgent
|
||||||
Sent received: Entrant / Sortant
|
Sent received: Entrant / Sortant
|
||||||
@ -50,10 +50,10 @@ received: Reçu
|
|||||||
|
|
||||||
|
|
||||||
#forms
|
#forms
|
||||||
Activity creation: Nouvelle activité
|
Activity creation: Nouvel échange
|
||||||
Create: Créer
|
Create: Créer
|
||||||
Back to the list: Retour à la liste
|
Back to the list: Retour à la liste
|
||||||
Save activity: Sauver l'activité
|
Save activity: Sauver l'échange
|
||||||
Reset form: Remise à zéro du formulaire
|
Reset form: Remise à zéro du formulaire
|
||||||
Choose the duration: Choisir la durée
|
Choose the duration: Choisir la durée
|
||||||
Choose a type: Choisir un type
|
Choose a type: Choisir un type
|
||||||
@ -90,40 +90,40 @@ activity:
|
|||||||
No documents: Aucun document
|
No documents: Aucun document
|
||||||
|
|
||||||
#timeline
|
#timeline
|
||||||
'%user% has done an %activity_type%': '%user% a effectué une activité de type "%activity_type%"'
|
'%user% has done an %activity_type%': '%user% a effectué un échange de type "%activity_type%"'
|
||||||
|
|
||||||
#controller
|
#controller
|
||||||
'Success : activity created!': L'activité a été créée.
|
'Success : activity created!': L'échange a été créé.
|
||||||
'The form is not valid. The activity has not been created !': Le formulaire est invalide. L'activité n'a pas été créée.
|
'The form is not valid. The activity has not been created !': Le formulaire est invalide. L'échange n'a pas été créé.
|
||||||
'Success : activity updated!': L'activité a été mise à jour.
|
'Success : activity updated!': L'échange a été mis à jour.
|
||||||
'The form is not valid. The activity has not been updated !': Le formulaire est invalide. L'activité n'a pas été mise à jour.
|
'The form is not valid. The activity has not been updated !': Le formulaire est invalide. L'échange n'a pas été mise à jour.
|
||||||
|
|
||||||
# ROLES
|
# ROLES
|
||||||
CHILL_ACTIVITY_CREATE: Créer une activité
|
CHILL_ACTIVITY_CREATE: Créer un échange
|
||||||
CHILL_ACTIVITY_UPDATE: Modifier une activité
|
CHILL_ACTIVITY_UPDATE: Modifier un échange
|
||||||
CHILL_ACTIVITY_SEE: Voir une activité
|
CHILL_ACTIVITY_SEE: Voir un échange
|
||||||
CHILL_ACTIVITY_SEE_DETAILS: Voir le détail des activités
|
CHILL_ACTIVITY_SEE_DETAILS: Voir le détail des échanges
|
||||||
CHILL_ACTIVITY_DELETE: Supprimer une activité
|
CHILL_ACTIVITY_DELETE: Supprimer un échange
|
||||||
CHILL_ACTIVITY_STATS: Statistique des activités
|
CHILL_ACTIVITY_STATS: Statistique des échanges
|
||||||
CHILL_ACTIVITY_LIST: Liste des activités
|
CHILL_ACTIVITY_LIST: Liste des échanges
|
||||||
|
|
||||||
# admin
|
# admin
|
||||||
Activities: Activités
|
Activities: Échanges
|
||||||
Activity configuration: Configuration des activités
|
Activity configuration: Configuration des échanges
|
||||||
Activity configuration menu: Configuration des activités
|
Activity configuration menu: Configuration des échanges
|
||||||
Activity types: Types d'activité
|
Activity types: Types d'échange
|
||||||
Activity type configuration: Configuration des categories d'activités
|
Activity type configuration: Configuration des catégories d'échanges
|
||||||
Activity Reasons: Sujets d'une activité
|
Activity Reasons: Sujets d'un échange
|
||||||
Activity Reasons Category: Catégories de sujet d'activités
|
Activity Reasons Category: Catégories de sujet d'échanges
|
||||||
Activity Types Categories: Catégories des types d'activité
|
Activity Types Categories: Catégories des types d'échange
|
||||||
Activity Presences: Presences aux activités
|
Activity Presences: Presences aux échanges
|
||||||
Associated activity reason category is inactive: La catégorie de sujet attachée est inactive
|
Associated activity reason category is inactive: La catégorie de sujet attachée est inactive
|
||||||
|
|
||||||
|
|
||||||
# Crud
|
# Crud
|
||||||
crud:
|
crud:
|
||||||
activity_type:
|
activity_type:
|
||||||
title_new: Nouveau type d'activité
|
title_new: Nouveau type d'échange
|
||||||
title_edit: Edition d'un type d'activité
|
title_edit: Edition d'un type d'activité
|
||||||
activity_type_category:
|
activity_type_category:
|
||||||
title_new: Nouvelle catégorie de type d'activité
|
title_new: Nouvelle catégorie de type d'activité
|
||||||
@ -159,8 +159,8 @@ Create a new activity presence: Créer une nouvelle "Présence aux activités"
|
|||||||
# activity type type admin
|
# activity type type admin
|
||||||
ActivityType list: Types d'activités
|
ActivityType list: Types d'activités
|
||||||
Create a new activity type: Créer un nouveau type d'activité
|
Create a new activity type: Créer un nouveau type d'activité
|
||||||
Persons visible: Visibilité du champ Personnes
|
Persons visible: Visibilité du champ Usagers
|
||||||
Persons label: Libellé du champ Personnes
|
Persons label: Libellé du champ Usagers
|
||||||
User visible: Visibilité du champ Utilisateur
|
User visible: Visibilité du champ Utilisateur
|
||||||
User label: Libellé du champ Utilisateur
|
User label: Libellé du champ Utilisateur
|
||||||
Date visible: Visibilité du champ Date
|
Date visible: Visibilité du champ Date
|
||||||
@ -183,8 +183,8 @@ Private comment visible: Visibilité du champ Commentaire Privé
|
|||||||
Private comment label: Libellé du champ Commentaire Privé
|
Private comment label: Libellé du champ Commentaire Privé
|
||||||
Emergency visible: Visibilité du champ Urgent
|
Emergency visible: Visibilité du champ Urgent
|
||||||
Emergency label: Libellé du champ Urgent
|
Emergency label: Libellé du champ Urgent
|
||||||
Accompanying period visible: Visibilité du champ Période d'accompagnement
|
Accompanying period visible: Visibilité du champ parcours d'accompagnement
|
||||||
Accompanying period label: Libellé du champ Période d'accompagnement
|
Accompanying period label: Libellé du champ parcours d'accompagnement
|
||||||
Social issues visible: Visibilité du champ Problématiques sociales
|
Social issues visible: Visibilité du champ Problématiques sociales
|
||||||
Social issues label: Libellé du champ Problématiques sociales
|
Social issues label: Libellé du champ Problématiques sociales
|
||||||
Social actions visible: Visibilité du champ Action sociale
|
Social actions visible: Visibilité du champ Action sociale
|
||||||
@ -206,10 +206,10 @@ Are you sure you want to remove the activity about "%name%" ?: Êtes-vous sûr d
|
|||||||
The activity has been successfully removed.: L'activité a été supprimée.
|
The activity has been successfully removed.: L'activité a été supprimée.
|
||||||
|
|
||||||
# exports
|
# exports
|
||||||
Exports of activities linked to a person: Exports des activités liées à une personne
|
Exports of activities linked to a person: Exports des activités liées à un usager
|
||||||
Number of activities linked to a person: Nombre d'activités liées à une personne
|
Number of activities linked to a person: Nombre d'activités liées à un usager
|
||||||
Count activities linked to a person: Nombre d'activités
|
Count activities linked to a person: Nombre d'activités
|
||||||
Count activities linked to a person by various parameters.: Compte le nombre d'activités enregistrées et liées à une personne en fonction de différents paramètres.
|
Count activities linked to a person by various parameters.: Compte le nombre d'activités enregistrées et liées à un usager en fonction de différents paramètres.
|
||||||
Sum activity linked to a person duration: Durée des activités
|
Sum activity linked to a person duration: Durée des activités
|
||||||
Sum activities linked to a person duration: Durée des activités liés à un usager
|
Sum activities linked to a person duration: Durée des activités liés à un usager
|
||||||
Sum activities linked to a person duration by various parameters.: Additionne la durée des activités en fonction de différents paramètres.
|
Sum activities linked to a person duration by various parameters.: Additionne la durée des activités en fonction de différents paramètres.
|
||||||
@ -244,10 +244,10 @@ Activities before this date: Activités avant cette date
|
|||||||
"Filtered by date of activity: only between %date_from% and %date_to%": "Filtré par date de l'activité: uniquement entre %date_from% et %date_to%"
|
"Filtered by date of activity: only between %date_from% and %date_to%": "Filtré par date de l'activité: uniquement entre %date_from% et %date_to%"
|
||||||
This date should be after the date given in "Implied in an activity after this date" field: Cette date devrait être postérieure à la date donnée dans le champ "activités après cette date"
|
This date should be after the date given in "Implied in an activity after this date" field: Cette date devrait être postérieure à la date donnée dans le champ "activités après cette date"
|
||||||
|
|
||||||
Filtered by person having an activity in a period: Uniquement les personnes ayant eu une activité dans la période donnée
|
Filtered by person having an activity in a period: Uniquement les usagers ayant eu une activité dans la période donnée
|
||||||
Implied in an activity after this date: Impliqué dans une activité après cette date
|
Implied in an activity after this date: Impliqué dans une activité après cette date
|
||||||
Implied in an activity before this date: Impliqué dans une activité avant cette date
|
Implied in an activity before this date: Impliqué dans une activité avant cette date
|
||||||
Filtered by person having an activity between %date_from% and %date_to% with reasons %reasons_name%: Filtré par personnes associées à une activité entre %date_from% et %date_to% avec les sujets %reasons_name%
|
Filtered by person having an activity between %date_from% and %date_to% with reasons %reasons_name%: Filtré par usager associées à une activité entre %date_from% et %date_to% avec les sujets %reasons_name%
|
||||||
Activity reasons for those activities: Sujets de ces activités
|
Activity reasons for those activities: Sujets de ces activités
|
||||||
|
|
||||||
Filter by activity type: Filtrer les activités par type
|
Filter by activity type: Filtrer les activités par type
|
||||||
@ -326,9 +326,11 @@ This is the minimal activity data: Activité n°
|
|||||||
|
|
||||||
docgen:
|
docgen:
|
||||||
Activity basic: Echange
|
Activity basic: Echange
|
||||||
A basic context for activity: Contexte pour les activités
|
A basic context for activity: Contexte pour les échanges
|
||||||
Accompanying period with a list of activities: Parcours d'accompagnement avec liste des activités
|
Accompanying period with a list of activities: Parcours d'accompagnement avec liste des échanges
|
||||||
Accompanying period with a list of activities description: Ce contexte reprend les informations du parcours, et tous les activités pour un parcours. Les activités ne sont pas filtrés.
|
Accompanying period with a list of activities description: Ce contexte reprend les informations du parcours, et tous les échanges pour un parcours. Les échanges ne sont pas filtrés.
|
||||||
|
myActivitiesOnly: Prendre en compte uniquement les échanges dans lesquels je suis intervenu
|
||||||
|
myWorksOnly: Prendre en compte uniquement les actions d'accompagnement dont je suis référent
|
||||||
|
|
||||||
export:
|
export:
|
||||||
list:
|
list:
|
||||||
@ -336,8 +338,8 @@ export:
|
|||||||
users name: Nom des utilisateurs
|
users name: Nom des utilisateurs
|
||||||
users ids: Identifiant des utilisateurs
|
users ids: Identifiant des utilisateurs
|
||||||
third parties ids: Identifiant des tiers
|
third parties ids: Identifiant des tiers
|
||||||
persons ids: Identifiant des personnes
|
persons ids: Identifiant des usagers
|
||||||
persons name: Nom des personnes
|
persons name: Nom des usagers
|
||||||
thirds parties: Tiers
|
thirds parties: Tiers
|
||||||
date: Date de l'activité
|
date: Date de l'activité
|
||||||
locationName: Localisation
|
locationName: Localisation
|
||||||
|
@ -47,10 +47,10 @@ Reasons: Onderwerpen
|
|||||||
|
|
||||||
|
|
||||||
#forms
|
#forms
|
||||||
Activity creation: Nouvelle activité
|
Activity creation: Nouvel échange
|
||||||
Create: Créer
|
Create: Créer
|
||||||
Back to the list: Retour à la liste
|
Back to the list: Retour à la liste
|
||||||
Save activity: Sauver l'activité
|
Save activity: Sauver l'échange
|
||||||
Reset form: Remise à zéro du formulaire
|
Reset form: Remise à zéro du formulaire
|
||||||
Choose the duration: Choisir la durée
|
Choose the duration: Choisir la durée
|
||||||
Choose a type: Choisir un type
|
Choose a type: Choisir un type
|
||||||
@ -79,43 +79,43 @@ activity:
|
|||||||
No documents: Aucun document
|
No documents: Aucun document
|
||||||
|
|
||||||
#timeline
|
#timeline
|
||||||
'%user% has done an %activity_type%': '%user% a effectué une activité de type "%activity_type%"'
|
'%user% has done an %activity_type%': '%user% a effectué un échange de type "%activity_type%"'
|
||||||
|
|
||||||
#controller
|
#controller
|
||||||
'Success : activity created!': L'activité a été créée.
|
'Success : activity created!': L'échange a été créé.
|
||||||
'The form is not valid. The activity has not been created !': Le formulaire est invalide. L'activité n'a pas été créée.
|
'The form is not valid. The activity has not been created !': Le formulaire est invalide. L'échange n'a pas été créé.
|
||||||
'Success : activity updated!': L'activité a été mise à jour.
|
'Success : activity updated!': L'échange a été mis à jour.
|
||||||
'The form is not valid. The activity has not been updated !': Le formulaire est invalide. L'activité n'a pas été mise à jour.
|
'The form is not valid. The activity has not been updated !': Le formulaire est invalide. L'échange n'a pas été mis à jour.
|
||||||
|
|
||||||
# ROLES
|
# ROLES
|
||||||
CHILL_ACTIVITY_CREATE: Créer une activité
|
CHILL_ACTIVITY_CREATE: Créer un échange
|
||||||
CHILL_ACTIVITY_UPDATE: Modifier une activité
|
CHILL_ACTIVITY_UPDATE: Modifier un échange
|
||||||
CHILL_ACTIVITY_SEE: Voir une activité
|
CHILL_ACTIVITY_SEE: Voir un échange
|
||||||
CHILL_ACTIVITY_SEE_DETAILS: Voir le détail des activités
|
CHILL_ACTIVITY_SEE_DETAILS: Voir le détail des échanges
|
||||||
CHILL_ACTIVITY_DELETE: Supprimer une activité
|
CHILL_ACTIVITY_DELETE: Supprimer un échange
|
||||||
CHILL_ACTIVITY_STATS: Statistique des activités
|
CHILL_ACTIVITY_STATS: Statistique des échanges
|
||||||
CHILL_ACTIVITY_LIST: Liste des activités
|
CHILL_ACTIVITY_LIST: Liste des échanges
|
||||||
|
|
||||||
# admin
|
# admin
|
||||||
Activities: Activités
|
Activities: Échanges
|
||||||
Activity configuration: Configuration des activités
|
Activity configuration: Configuration des échanges
|
||||||
Activity configuration menu: Configuration des activités
|
Activity configuration menu: Configuration des échanges
|
||||||
Activity types: Types d'activité
|
Activity types: Types d'échange
|
||||||
Activity type configuration: Configuration des categories d'activités
|
Activity type configuration: Configuration des categories d'échanges
|
||||||
Activity Reasons: Sujets d'une activité
|
Activity Reasons: Sujets d'un échange
|
||||||
Activity Reasons Category: Catégories de sujet d'activités
|
Activity Reasons Category: Catégories de sujet d'échanges
|
||||||
Activity Types Categories: Catégories des types d'activité
|
Activity Types Categories: Catégories des types d'échanges
|
||||||
Activity Presences: Presences des activités
|
Activity Presences: Presences des échanges
|
||||||
|
|
||||||
|
|
||||||
# Crud
|
# Crud
|
||||||
crud:
|
crud:
|
||||||
activity_type:
|
activity_type:
|
||||||
title_new: Nouveau type d'activité
|
title_new: Nouveau type d'échange
|
||||||
title_edit: Edition d'un type d'activité
|
title_edit: Edition d'un type d'échange
|
||||||
activity_type_category:
|
activity_type_category:
|
||||||
title_new: Nouvelle catégorie de type d'activité
|
title_new: Nouvelle catégorie de type d'échange
|
||||||
title_edit: Edition d'une catégorie de type d'activité
|
title_edit: Edition d'une catégorie de type d'échange
|
||||||
|
|
||||||
# activity reason admin
|
# activity reason admin
|
||||||
ActivityReason list: Liste des sujets
|
ActivityReason list: Liste des sujets
|
||||||
@ -124,7 +124,7 @@ Active: Actif
|
|||||||
Category: Catégorie
|
Category: Catégorie
|
||||||
ActivityReason creation: Nouveau sujet
|
ActivityReason creation: Nouveau sujet
|
||||||
ActivityReason edit: Modification d'un sujet
|
ActivityReason edit: Modification d'un sujet
|
||||||
ActivityReason: Sujet d'activité
|
ActivityReason: Sujet d'échange
|
||||||
The entity is inactive and won't be proposed: Le sujet est inactif et ne sera pas proposé
|
The entity is inactive and won't be proposed: Le sujet est inactif et ne sera pas proposé
|
||||||
The entity is active and will be proposed: Le sujet est actif et sera proposé
|
The entity is active and will be proposed: Le sujet est actif et sera proposé
|
||||||
|
|
||||||
@ -133,13 +133,13 @@ ActivityReasonCategory list: Catégories de sujets
|
|||||||
Create a new activity category reason: Créer une nouvelle catégorie
|
Create a new activity category reason: Créer une nouvelle catégorie
|
||||||
ActivityReasonCategory creation: Nouvelle catégorie de sujet
|
ActivityReasonCategory creation: Nouvelle catégorie de sujet
|
||||||
ActivityReasonCategory edit: Modification d'une catégorie de sujet
|
ActivityReasonCategory edit: Modification d'une catégorie de sujet
|
||||||
ActivityReasonCategory: Catégorie de sujet d'activité
|
ActivityReasonCategory: Catégorie de sujet d'échange
|
||||||
ActivityReasonCategory is active and will be proposed: La catégorie est active et sera proposée
|
ActivityReasonCategory is active and will be proposed: La catégorie est active et sera proposée
|
||||||
ActivityReasonCategory is inactive and won't be proposed: La catégorie est inactive et ne sera pas proposée
|
ActivityReasonCategory is inactive and won't be proposed: La catégorie est inactive et ne sera pas proposée
|
||||||
|
|
||||||
# activity type type admin
|
# activity type type admin
|
||||||
ActivityType list: Types d'activités
|
ActivityType list: Types d'échanges
|
||||||
Create a new activity type: Créer un nouveau type d'activité
|
Create a new activity type: Créer un nouveau type d'échange
|
||||||
Persons visible: Visibilité du champ Personnes
|
Persons visible: Visibilité du champ Personnes
|
||||||
Persons label: Libellé du champ Personnes
|
Persons label: Libellé du champ Personnes
|
||||||
User visible: Visibilité du champ Utilisateur
|
User visible: Visibilité du champ Utilisateur
|
||||||
@ -177,20 +177,20 @@ Documents label: Libellé du champ Documents
|
|||||||
|
|
||||||
# activity type category admin
|
# activity type category admin
|
||||||
ActivityTypeCategory list: Liste des catégories des types d'activité
|
ActivityTypeCategory list: Liste des catégories des types d'activité
|
||||||
Create a new activity type category: Créer une nouvelle catégorie de type d'activité
|
Create a new activity type category: Créer une nouvelle catégorie de type d'échange
|
||||||
|
|
||||||
# activity delete
|
# activity delete
|
||||||
Remove activity: Supprimer une activité
|
Remove activity: Supprimer un échange
|
||||||
Are you sure you want to remove the activity about "%name%" ?: Êtes-vous sûr de vouloir supprimer une activité qui concerne "%name%" ?
|
Are you sure you want to remove the activity about "%name%" ?: Êtes-vous sûr de vouloir supprimer un échange qui concerne "%name%" ?
|
||||||
The activity has been successfully removed.: L'activité a été supprimée.
|
The activity has been successfully removed.: L'échange a été supprimée.
|
||||||
|
|
||||||
# exports
|
# exports
|
||||||
Count activities: Nombre d'activités
|
Count activities: Nombre d'échanges
|
||||||
Count activities by various parameters.: Compte le nombre d'activités enregistrées en fonction de différents paramètres.
|
Count activities by various parameters.: Compte le nombre d'échanges enregistrées en fonction de différents paramètres.
|
||||||
Sum activity duration: Total de la durée des activités
|
Sum activity duration: Total de la durée des échanges
|
||||||
Sum activities duration by various parameters.: Additionne la durée des activités en fonction de différents paramètres.
|
Sum activities duration by various parameters.: Additionne la durée des échanges en fonction de différents paramètres.
|
||||||
List activities: Liste les activités
|
List activities: Liste les échanges
|
||||||
Number of activities: Nombre d'activités
|
Number of activities: Nombre d'échanges
|
||||||
|
|
||||||
#filters
|
#filters
|
||||||
Filter by reason: Filtrer par sujet d'activité
|
Filter by reason: Filtrer par sujet d'activité
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
The reasons's level should not be empty: Le niveau du sujet ne peut pas être vide
|
The reasons's level should not be empty: Le niveau du sujet ne peut pas être vide
|
||||||
At least one reason must be choosen: Au moins un sujet doit être choisi
|
At least one reason must be choosen: Au moins un sujet doit être choisi
|
||||||
For this type of activity, you must add at least one person: Pour ce type d'activité, vous devez ajouter au moins un usager
|
For this type of activity, you must add at least one person: Pour ce type d'échange, vous devez ajouter au moins un usager
|
||||||
For this type of activity, you must add at least one user: Pour ce type d'activité, vous devez ajouter au moins un utilisateur
|
For this type of activity, you must add at least one user: Pour ce type d'échange, vous devez ajouter au moins un utilisateur
|
||||||
For this type of activity, you must add at least one third party: Pour ce type d'activité, vous devez ajouter au moins un tiers
|
For this type of activity, you must add at least one third party: Pour ce type d'échange, vous devez ajouter au moins un tiers
|
||||||
For this type of activity, user is required: Pour ce type d'activité, l'utilisateur est requis
|
For this type of activity, user is required: Pour ce type d'échange, l'utilisateur est requis
|
||||||
For this type of activity, date is required: Pour ce type d'activité, la date est requise
|
For this type of activity, date is required: Pour ce type d'échange, la date est requise
|
||||||
For this type of activity, location is required: Pour ce type d'activité, la localisation est requise
|
For this type of activity, location is required: Pour ce type d'échange, la localisation est requise
|
||||||
For this type of activity, attendee is required: Pour ce type d'activité, le champ "Présence de la personne" est requis
|
For this type of activity, attendee is required: Pour ce type d'échange, le champ "Présence de l'usager" est requis
|
||||||
For this type of activity, duration time is required: Pour ce type d'activité, la durée est requise
|
For this type of activity, duration time is required: Pour ce type d'échange, la durée est requise
|
||||||
For this type of activity, travel time is required: Pour ce type d'activité, la durée du trajet est requise
|
For this type of activity, travel time is required: Pour ce type d'échange, la durée du trajet est requise
|
||||||
For this type of activity, reasons is required: Pour ce type d'activité, le champ "sujet" est requis
|
For this type of activity, reasons is required: Pour ce type d'échange, le champ "sujet" est requis
|
||||||
For this type of activity, comment is required: Pour ce type d'activité, un commentaire est requis
|
For this type of activity, comment is required: Pour ce type d'échange, un commentaire est requis
|
||||||
For this type of activity, sent/received is required: Pour ce type d'activité, le champ Entrant/Sortant est requis
|
For this type of activity, sent/received is required: Pour ce type d'échange, le champ Entrant/Sortant est requis
|
||||||
For this type of activity, document is required: Pour ce type d'activité, un document est requis
|
For this type of activity, document is required: Pour ce type d'échange, un document est requis
|
||||||
For this type of activity, emergency is required: Pour ce type d'activité, le champ "Urgent" est requis
|
For this type of activity, emergency is required: Pour ce type d'échange, le champ "Urgent" est requis
|
||||||
For this type of activity, accompanying period is required: Pour ce type d'activité, le parcours d'accompagnement est requis
|
For this type of activity, accompanying period is required: Pour ce type d'échange, le parcours d'accompagnement est requis
|
||||||
For this type of activity, you must add at least one social issue: Pour ce type d'activité, vous devez ajouter au moins une problématique sociale
|
For this type of activity, you must add at least one social issue: Pour ce type d'échange, vous devez ajouter au moins une problématique sociale
|
||||||
For this type of activity, you must add at least one social action: Pour ce type d'activité, vous devez indiquer au moins une action sociale
|
For this type of activity, you must add at least one social action: Pour ce type d'échange, vous devez indiquer au moins une action sociale
|
||||||
|
|
||||||
# admin
|
# admin
|
||||||
This parameter must be equal to social issue parameter: Ce paramètre doit être égal au paramètre "Visibilité du champs Problématiques sociales"
|
This parameter must be equal to social issue parameter: Ce paramètre doit être égal au paramètre "Visibilité du champs Problématiques sociales"
|
||||||
|
@ -160,8 +160,8 @@ final class ListAsideActivity implements ListInterface, GroupedExportInterface
|
|||||||
return 'export.aside_activity.main_center';
|
return 'export.aside_activity.main_center';
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var Center $c */
|
|
||||||
if (null === $value || '' === $value || null === $c = $this->centerRepository->find($value)) {
|
if (null === $value || '' === $value || null === $c = $this->centerRepository->find($value)) {
|
||||||
|
/** @var Center $c */
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,10 +190,6 @@ final class ListAsideActivity implements ListInterface, GroupedExportInterface
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param QueryBuilder $query
|
|
||||||
* @param array $data
|
|
||||||
*/
|
|
||||||
public function getResult($query, $data): array
|
public function getResult($query, $data): array
|
||||||
{
|
{
|
||||||
return $query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY);
|
return $query->getQuery()->getResult(AbstractQuery::HYDRATE_ARRAY);
|
||||||
|
@ -28,22 +28,17 @@ use Symfony\Component\Form\FormBuilderInterface;
|
|||||||
use Symfony\Component\Form\FormEvent;
|
use Symfony\Component\Form\FormEvent;
|
||||||
use Symfony\Component\Form\FormEvents;
|
use Symfony\Component\Form\FormEvents;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
|
||||||
|
|
||||||
use function in_array;
|
use function in_array;
|
||||||
|
|
||||||
final class AsideActivityFormType extends AbstractType
|
final class AsideActivityFormType extends AbstractType
|
||||||
{
|
{
|
||||||
private TokenStorageInterface $storage;
|
|
||||||
|
|
||||||
private array $timeChoices;
|
private array $timeChoices;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ParameterBagInterface $parameterBag,
|
ParameterBagInterface $parameterBag,
|
||||||
TokenStorageInterface $storage
|
|
||||||
) {
|
) {
|
||||||
$this->timeChoices = $parameterBag->get('chill_aside_activity.form.time_duration');
|
$this->timeChoices = $parameterBag->get('chill_aside_activity.form.time_duration');
|
||||||
$this->storage = $storage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||||
|
@ -44,17 +44,6 @@ class SectionMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
'order' => 11,
|
'order' => 11,
|
||||||
'icons' => ['plus'],
|
'icons' => ['plus'],
|
||||||
]);
|
]);
|
||||||
$menu->addChild($this->translator->trans('Phonecall'), [
|
|
||||||
'route' => 'chill_crud_aside_activity_new',
|
|
||||||
'routeParameters' => [
|
|
||||||
'type' => 1,
|
|
||||||
'duration' => 900,
|
|
||||||
],
|
|
||||||
])
|
|
||||||
->setExtras([
|
|
||||||
'order' => 12,
|
|
||||||
'icons' => ['plus'],
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ Type: Type
|
|||||||
Invisible: Invisible
|
Invisible: Invisible
|
||||||
Optional: Optionnel
|
Optional: Optionnel
|
||||||
Required: Obligatoire
|
Required: Obligatoire
|
||||||
Persons: Personnes
|
Persons: Usagers
|
||||||
Users: Utilisateurs
|
Users: Utilisateurs
|
||||||
Emergency: Urgent
|
Emergency: Urgent
|
||||||
by: "Par "
|
by: "Par "
|
||||||
@ -50,7 +50,7 @@ For agent: Pour l'utilisateur
|
|||||||
date: Date
|
date: Date
|
||||||
Duration: Durée
|
Duration: Durée
|
||||||
Note: Note
|
Note: Note
|
||||||
Choose the agent for whom this activity is created: Choisissez l'agent pour qui l'activité est créée
|
Choose the agent for whom this activity is created: Choisissez l'agent pour qui l'échange est créé
|
||||||
Choose the activity category: Choisir la catégorie
|
Choose the activity category: Choisir la catégorie
|
||||||
|
|
||||||
#Duration
|
#Duration
|
||||||
|
@ -33,27 +33,15 @@ class ElementController extends AbstractController
|
|||||||
{
|
{
|
||||||
private CalculatorManager $calculator;
|
private CalculatorManager $calculator;
|
||||||
|
|
||||||
private LoggerInterface $chillMainLogger;
|
|
||||||
|
|
||||||
private EntityManagerInterface $em;
|
|
||||||
|
|
||||||
private ResourceRepository $resourceRepository;
|
private ResourceRepository $resourceRepository;
|
||||||
|
|
||||||
private ChargeRepository $chargeRepository;
|
private ChargeRepository $chargeRepository;
|
||||||
|
|
||||||
private TranslatorInterface $translator;
|
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
EntityManagerInterface $em,
|
|
||||||
TranslatorInterface $translator,
|
|
||||||
LoggerInterface $chillMainLogger,
|
|
||||||
CalculatorManager $calculator,
|
CalculatorManager $calculator,
|
||||||
ResourceRepository $resourceRepository,
|
ResourceRepository $resourceRepository,
|
||||||
ChargeRepository $chargeRepository,
|
ChargeRepository $chargeRepository,
|
||||||
) {
|
) {
|
||||||
$this->em = $em;
|
|
||||||
$this->translator = $translator;
|
|
||||||
$this->chillMainLogger = $chillMainLogger;
|
|
||||||
$this->calculator = $calculator;
|
$this->calculator = $calculator;
|
||||||
$this->resourceRepository = $resourceRepository;
|
$this->resourceRepository = $resourceRepository;
|
||||||
$this->chargeRepository = $chargeRepository;
|
$this->chargeRepository = $chargeRepository;
|
||||||
|
@ -30,7 +30,7 @@ final class ChargeKindRepository implements ChargeKindRepositoryInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ChargeType[]
|
* @return array<ChargeKind>
|
||||||
*/
|
*/
|
||||||
public function findAll(): array
|
public function findAll(): array
|
||||||
{
|
{
|
||||||
@ -38,7 +38,7 @@ final class ChargeKindRepository implements ChargeKindRepositoryInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ChargeType[]
|
* @return array<ChargeKind>
|
||||||
*/
|
*/
|
||||||
public function findAllActive(): array
|
public function findAllActive(): array
|
||||||
{
|
{
|
||||||
@ -53,7 +53,7 @@ final class ChargeKindRepository implements ChargeKindRepositoryInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ChargeType[]
|
* @return array<ChargeKind>
|
||||||
*/
|
*/
|
||||||
public function findAllByType(string $type): array
|
public function findAllByType(string $type): array
|
||||||
{
|
{
|
||||||
@ -64,7 +64,7 @@ final class ChargeKindRepository implements ChargeKindRepositoryInterface
|
|||||||
* @param mixed|null $limit
|
* @param mixed|null $limit
|
||||||
* @param mixed|null $offset
|
* @param mixed|null $offset
|
||||||
*
|
*
|
||||||
* @return ChargeType[]
|
* @return array<ChargeKind>
|
||||||
*/
|
*/
|
||||||
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
|
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
|
||||||
{
|
{
|
||||||
|
@ -19,25 +19,25 @@ interface ChargeKindRepositoryInterface extends ObjectRepository
|
|||||||
public function find($id): ?ChargeKind;
|
public function find($id): ?ChargeKind;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ChargeType[]
|
* @return array<ChargeKind>
|
||||||
*/
|
*/
|
||||||
public function findAll(): array;
|
public function findAll(): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ChargeType[]
|
* @return array<ChargeKind>
|
||||||
*/
|
*/
|
||||||
public function findAllActive(): array;
|
public function findAllActive(): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ChargeType[]
|
* @return array<ChargeKind>
|
||||||
*/
|
*/
|
||||||
public function findAllByType(string $type): array;
|
public function findAllByType(string $type): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed|null $limit
|
* @param int|null $limit
|
||||||
* @param mixed|null $offset
|
* @param int|null $offset
|
||||||
*
|
*
|
||||||
* @return ChargeType[]
|
* @return array<ChargeKind>
|
||||||
*/
|
*/
|
||||||
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array;
|
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array;
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ final class ResourceKindRepository implements ResourceKindRepositoryInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ResourceType[]
|
* @return list<ResourceKind>
|
||||||
*/
|
*/
|
||||||
public function findAll(): array
|
public function findAll(): array
|
||||||
{
|
{
|
||||||
@ -38,7 +38,7 @@ final class ResourceKindRepository implements ResourceKindRepositoryInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ResourceType[]
|
* @return list<ResourceKind>
|
||||||
*/
|
*/
|
||||||
public function findAllActive(): array
|
public function findAllActive(): array
|
||||||
{
|
{
|
||||||
@ -58,7 +58,7 @@ final class ResourceKindRepository implements ResourceKindRepositoryInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ResourceType[]
|
* @return list<ResourceKind>
|
||||||
*/
|
*/
|
||||||
public function findAllByType(string $type): array
|
public function findAllByType(string $type): array
|
||||||
{
|
{
|
||||||
@ -69,7 +69,7 @@ final class ResourceKindRepository implements ResourceKindRepositoryInterface
|
|||||||
* @param mixed|null $limit
|
* @param mixed|null $limit
|
||||||
* @param mixed|null $offset
|
* @param mixed|null $offset
|
||||||
*
|
*
|
||||||
* @return ResourceType[]
|
* @return list<ResourceKind>
|
||||||
*/
|
*/
|
||||||
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
|
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
|
||||||
{
|
{
|
||||||
|
@ -19,25 +19,25 @@ interface ResourceKindRepositoryInterface extends ObjectRepository
|
|||||||
public function find($id): ?ResourceKind;
|
public function find($id): ?ResourceKind;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ResourceType[]
|
* @return list<ResourceKind>
|
||||||
*/
|
*/
|
||||||
public function findAll(): array;
|
public function findAll(): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ResourceType[]
|
* @return list<ResourceKind>
|
||||||
*/
|
*/
|
||||||
public function findAllActive(): array;
|
public function findAllActive(): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return ResourceType[]
|
* @return list<ResourceKind>
|
||||||
*/
|
*/
|
||||||
public function findAllByType(string $type): array;
|
public function findAllByType(string $type): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed|null $limit
|
* @param int|null $limit
|
||||||
* @param mixed|null $offset
|
* @param int|null $offset
|
||||||
*
|
*
|
||||||
* @return ResourceType[]
|
* @return list<ResourceKind>
|
||||||
*/
|
*/
|
||||||
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array;
|
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array;
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ End of validity period: Fin de la période de validité
|
|||||||
Total: Total
|
Total: Total
|
||||||
Create new resource: Créer une nouvelle ressource
|
Create new resource: Créer une nouvelle ressource
|
||||||
Create new charge: Créer une nouvelle charge
|
Create new charge: Créer une nouvelle charge
|
||||||
See person: Voir personne
|
See person: Voir usagers
|
||||||
|
|
||||||
There isn't any element recorded: Aucun élément enregistré
|
There isn't any element recorded: Aucun élément enregistré
|
||||||
No resources registered: Aucune ressource enregistrée
|
No resources registered: Aucune ressource enregistrée
|
||||||
|
@ -207,6 +207,7 @@ class CalendarController extends AbstractController
|
|||||||
'entityClassName' => Calendar::class,
|
'entityClassName' => Calendar::class,
|
||||||
'entityId' => $entity->getId(),
|
'entityId' => $entity->getId(),
|
||||||
'template' => $template->getId(),
|
'template' => $template->getId(),
|
||||||
|
'returnPath' => $request->getRequestUri(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -377,7 +378,9 @@ class CalendarController extends AbstractController
|
|||||||
$this->addFlash('success', $this->translator->trans('Success : calendar item created!'));
|
$this->addFlash('success', $this->translator->trans('Success : calendar item created!'));
|
||||||
|
|
||||||
if ($form->get('save_and_upload_doc')->isClicked()) {
|
if ($form->get('save_and_upload_doc')->isClicked()) {
|
||||||
return $this->redirectToRoute('chill_calendar_calendardoc_new', ['id' => $entity->getId()]);
|
return $this->redirectToRoute('chill_calendar_calendardoc_new', [
|
||||||
|
'id' => $entity->getId()
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($templates as $template) {
|
foreach ($templates as $template) {
|
||||||
@ -386,6 +389,7 @@ class CalendarController extends AbstractController
|
|||||||
'entityClassName' => Calendar::class,
|
'entityClassName' => Calendar::class,
|
||||||
'entityId' => $entity->getId(),
|
'entityId' => $entity->getId(),
|
||||||
'template' => $template->getId(),
|
'template' => $template->getId(),
|
||||||
|
'returnPath' => $this->generateUrl('chill_calendar_calendar_edit', ['id' => $entity->getId()]),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -526,14 +530,20 @@ class CalendarController extends AbstractController
|
|||||||
'comment' => $calendar->getComment()->getComment(),
|
'comment' => $calendar->getComment()->getComment(),
|
||||||
];
|
];
|
||||||
|
|
||||||
return $this->redirectToRoute(
|
$routeParams = [
|
||||||
'chill_activity_activity_new',
|
|
||||||
[
|
|
||||||
'accompanying_period_id' => $calendar->getAccompanyingPeriod()->getId(),
|
|
||||||
'activityData' => $activityData,
|
'activityData' => $activityData,
|
||||||
'returnPath' => $request->query->get('returnPath', null),
|
'returnPath' => $request->query->get('returnPath', null),
|
||||||
]
|
];
|
||||||
);
|
|
||||||
|
if ($calendar->getContext() === 'accompanying_period') {
|
||||||
|
$routeParams['accompanying_period_id'] = $calendar->getAccompanyingPeriod()->getId();
|
||||||
|
} elseif ($calendar->getContext() === 'person') {
|
||||||
|
$routeParams['person_id'] = $calendar->getPerson()->getId();
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException('context not found for this calendar');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->redirectToRoute('chill_activity_activity_new', $routeParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildListFilterOrder(): FilterOrderHelper
|
private function buildListFilterOrder(): FilterOrderHelper
|
||||||
@ -544,21 +554,6 @@ class CalendarController extends AbstractController
|
|||||||
return $filterOrder->build();
|
return $filterOrder->build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildParamsToUrl(?User $user, ?AccompanyingPeriod $accompanyingPeriod): array
|
|
||||||
{
|
|
||||||
$params = [];
|
|
||||||
|
|
||||||
if (null !== $user) {
|
|
||||||
$params['user_id'] = $user->getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null !== $accompanyingPeriod) {
|
|
||||||
$params['id'] = $accompanyingPeriod->getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $params;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a form to delete a Calendar entity by id.
|
* Creates a form to delete a Calendar entity by id.
|
||||||
*/
|
*/
|
||||||
|
@ -29,6 +29,7 @@ use DateTimeImmutable;
|
|||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\Common\Collections\Criteria;
|
use Doctrine\Common\Collections\Criteria;
|
||||||
|
use Doctrine\Common\Collections\ReadableCollection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use LogicException;
|
use LogicException;
|
||||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||||
@ -92,6 +93,7 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface, HasCente
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod", inversedBy="calendars")
|
* @ORM\ManyToOne(targetEntity="Chill\PersonBundle\Entity\AccompanyingPeriod", inversedBy="calendars")
|
||||||
|
* @Serializer\Groups({"calendar:read", "read"})
|
||||||
*/
|
*/
|
||||||
private ?AccompanyingPeriod $accompanyingPeriod = null;
|
private ?AccompanyingPeriod $accompanyingPeriod = null;
|
||||||
|
|
||||||
@ -507,10 +509,10 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface, HasCente
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Collection|User[]
|
* @return ReadableCollection<(int|string), User>
|
||||||
* @Serializer\Groups({"calendar:read", "read"})
|
* @Serializer\Groups({"calendar:read", "read"})
|
||||||
*/
|
*/
|
||||||
public function getUsers(): Collection
|
public function getUsers(): ReadableCollection
|
||||||
{
|
{
|
||||||
return $this->getInvites()->map(static function (Invite $i) {
|
return $this->getInvites()->map(static function (Invite $i) {
|
||||||
return $i->getUser();
|
return $i->getUser();
|
||||||
|
@ -52,7 +52,7 @@ class CountCalendars implements ExportInterface, GroupedExportInterface
|
|||||||
return 'Exports of calendar';
|
return 'Exports of calendar';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLabels($key, array $values, $data): Closure
|
public function getLabels($key, array $values, $data)
|
||||||
{
|
{
|
||||||
if ('export_result' !== $key) {
|
if ('export_result' !== $key) {
|
||||||
throw new LogicException("the key {$key} is not used by this export");
|
throw new LogicException("the key {$key} is not used by this export");
|
||||||
|
@ -26,9 +26,6 @@ class CalendarDocEditType extends AbstractType
|
|||||||
->add('title', TextType::class, [
|
->add('title', TextType::class, [
|
||||||
'label' => 'chill_calendar.Document title',
|
'label' => 'chill_calendar.Document title',
|
||||||
'required' => true,
|
'required' => true,
|
||||||
])
|
|
||||||
->add('doc', StoredObjectType::class, [
|
|
||||||
'label' => 'chill_calendar.Document object',
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
:picked="null !== this.$store.getters.getMainUser ? [this.$store.getters.getMainUser] : []"
|
:picked="null !== this.$store.getters.getMainUser ? [this.$store.getters.getMainUser] : []"
|
||||||
:removableIfSet="false"
|
:removableIfSet="false"
|
||||||
:displayPicked="false"
|
:displayPicked="false"
|
||||||
|
:suggested="this.suggestedUsers"
|
||||||
@addNewEntity="setMainUser"
|
@addNewEntity="setMainUser"
|
||||||
></pick-entity>
|
></pick-entity>
|
||||||
</div>
|
</div>
|
||||||
@ -143,6 +144,7 @@ export default {
|
|||||||
slotMinTime: '09:00:00',
|
slotMinTime: '09:00:00',
|
||||||
slotMaxTime: '18:00:00',
|
slotMaxTime: '18:00:00',
|
||||||
hideWeekEnds: true,
|
hideWeekEnds: true,
|
||||||
|
previousUser: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -188,11 +190,23 @@ export default {
|
|||||||
users.push(this.$store.getters.getUserDataById(id).user);
|
users.push(this.$store.getters.getUserDataById(id).user);
|
||||||
}
|
}
|
||||||
return users;
|
return users;
|
||||||
|
},
|
||||||
|
suggestedUsers() {
|
||||||
|
const suggested = [];
|
||||||
|
|
||||||
|
this.$data.previousUser.forEach(u => {
|
||||||
|
if (u.id !== this.$store.getters.getMainUser.id) {
|
||||||
|
suggested.push(u)
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return suggested;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setMainUser(user) {
|
setMainUser({entity}) {
|
||||||
console.log('setMainUser APP', user);
|
const user = entity;
|
||||||
|
console.log('setMainUser APP', entity);
|
||||||
|
|
||||||
if (user.id !== this.$store.getters.getMainUser && (
|
if (user.id !== this.$store.getters.getMainUser && (
|
||||||
this.$store.state.activity.calendarRange !== null
|
this.$store.state.activity.calendarRange !== null
|
||||||
@ -205,6 +219,14 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add the previous user, if any, in the previous user list (in use for suggestion)
|
||||||
|
if (null !== this.$store.getters.getMainUser) {
|
||||||
|
const suggestedUids = new Set(this.$data.previousUser.map(u => u.id));
|
||||||
|
if (!suggestedUids.has(this.$store.getters.getMainUser.id)){
|
||||||
|
this.$data.previousUser.push(this.$store.getters.getMainUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.$store.dispatch('setMainUser', user);
|
this.$store.dispatch('setMainUser', user);
|
||||||
this.$store.commit('showUserOnCalendar', {user, ranges: true, remotes: true});
|
this.$store.commit('showUserOnCalendar', {user, ranges: true, remotes: true});
|
||||||
},
|
},
|
||||||
|
@ -202,6 +202,8 @@ export default {
|
|||||||
|
|
||||||
return dispatch('associateCalendarToRange', { range: null }).then(() => {
|
return dispatch('associateCalendarToRange', { range: null }).then(() => {
|
||||||
commit('setMainUser', mainUser);
|
commit('setMainUser', mainUser);
|
||||||
|
|
||||||
|
return dispatch('fetchCalendarEvents');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ export const mapEntity = (entity: EventInput): EventInput => {
|
|||||||
|
|
||||||
export const createUserData = (user: User, colorIndex: number): UserData => {
|
export const createUserData = (user: User, colorIndex: number): UserData => {
|
||||||
const colorId = colorIndex % COLORS.length;
|
const colorId = colorIndex % COLORS.length;
|
||||||
console.log('colorId', colorId);
|
|
||||||
return {
|
return {
|
||||||
user: user,
|
user: user,
|
||||||
calendarRanges: [],
|
calendarRanges: [],
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm">
|
<div class="col-sm">
|
||||||
<label class="form-label">Lieu des plages de disponibilités créées</label>
|
<label class="form-label">{{ $t('created_availabilities') }}</label>
|
||||||
<vue-multiselect
|
<vue-multiselect
|
||||||
v-model="pickedLocation"
|
v-model="pickedLocation"
|
||||||
:options="locations"
|
:options="locations"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const appMessages = {
|
const appMessages = {
|
||||||
fr: {
|
fr: {
|
||||||
|
created_availabilities: "Lieu des plages de disponibilités créées",
|
||||||
edit_your_calendar_range: "Planifiez vos plages de disponibilités",
|
edit_your_calendar_range: "Planifiez vos plages de disponibilités",
|
||||||
show_my_calendar: "Afficher mon calendrier",
|
show_my_calendar: "Afficher mon calendrier",
|
||||||
show_weekends: "Afficher les week-ends",
|
show_weekends: "Afficher les week-ends",
|
||||||
|
@ -20,15 +20,24 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col text-start">
|
<div class="col text-start">
|
||||||
{{ d.storedObject.title }}
|
{{ d.storedObject.title }}
|
||||||
|
</div>
|
||||||
{% if d.dateTimeVersion < d.calendar.dateTimeVersion %}
|
{% if d.dateTimeVersion < d.calendar.dateTimeVersion %}
|
||||||
|
<div class="col text-start">
|
||||||
<span class="badge bg-danger">{{ 'chill_calendar.Document outdated'|trans }}</span>
|
<span class="badge bg-danger">{{ 'chill_calendar.Document outdated'|trans }}</span>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
|
||||||
<div class="col-md-auto text-center">
|
|
||||||
{{ mm.mimeIcon(d.storedObject.type) }}
|
|
||||||
</div>
|
|
||||||
<div class="col col-lg-4 text-end">
|
<div class="col col-lg-4 text-end">
|
||||||
|
<ul class="record_actions">
|
||||||
|
<li>
|
||||||
{{ d.storedObject|chill_document_button_group(d.storedObject.title, is_granted('CHILL_CALENDAR_DOC_EDIT', d), {'small': true}) }}
|
{{ d.storedObject|chill_document_button_group(d.storedObject.title, is_granted('CHILL_CALENDAR_DOC_EDIT', d), {'small': true}) }}
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ chill_path_add_return_path('chill_calendar_calendardoc_edit', {id: d.id}) }}" class="btn btn-sm btn-edit"></a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="{{ chill_path_add_return_path('chill_calendar_calendardoc_delete', {id: d.id}) }}" class="btn btn-sm btn-delete"></a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
@ -110,7 +110,46 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="item-row">
|
{% if calendar.activity is not null %}
|
||||||
|
<div class="item-row separator">
|
||||||
|
<div class="item-col">
|
||||||
|
<div class="wrap-list">
|
||||||
|
<div class="wl-row">
|
||||||
|
<div class="wl-col title"><h3>{{ 'Activity'|trans }}</h3></div>
|
||||||
|
<div class="wl-col list activity-linked">
|
||||||
|
<h2 class="badge-title">
|
||||||
|
<span class="title_label"></span>
|
||||||
|
<span class="title_action">
|
||||||
|
{{ calendar.activity.type.name | localize_translatable_string }}
|
||||||
|
|
||||||
|
{% if calendar.activity.emergency %}
|
||||||
|
<span class="badge bg-danger rounded-pill fs-6 float-end">{{ 'Emergency'|trans|upper }}</span>
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<ul class="record_actions">
|
||||||
|
<li class="cancel">
|
||||||
|
<span class="createdBy">
|
||||||
|
{{ 'Created by'|trans }}
|
||||||
|
<b>{{ calendar.activity.createdBy|chill_entity_render_string }}</b>, {{ 'on'|trans }} {{ calendar.activity.createdAt|format_datetime('short', 'short') }}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
{% if is_granted('CHILL_ACTIVITY_SEE', calendar.activity) %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ chill_path_add_return_path('chill_activity_activity_show', {'id': calendar.activity.id}) }}" class="btn btn-sm btn-show" ></a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<div class="item-row separator">
|
||||||
<ul class="record_actions">
|
<ul class="record_actions">
|
||||||
{% if is_granted('CHILL_CALENDAR_CALENDAR_SEE', calendar) %}
|
{% if is_granted('CHILL_CALENDAR_CALENDAR_SEE', calendar) %}
|
||||||
{% if templates|length == 0 %}
|
{% if templates|length == 0 %}
|
||||||
@ -147,7 +186,12 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if accompanyingCourse is defined and is_granted('CHILL_ACTIVITY_CREATE', accompanyingCourse) and calendar.activity is null %}
|
{% if calendar.activity is null and (
|
||||||
|
(calendar.context == 'accompanying_period' and is_granted('CHILL_ACTIVITY_CREATE', calendar.accompanyingPeriod))
|
||||||
|
or
|
||||||
|
(calendar.context == 'person' and is_granted('CHILL_ACTIVITY_CREATE', calendar.person))
|
||||||
|
)
|
||||||
|
%}
|
||||||
<li>
|
<li>
|
||||||
<a class="btn btn-create"
|
<a class="btn btn-create"
|
||||||
href="{{ chill_path_add_return_path('chill_calendar_calendar_to_activity', { 'id': calendar.id }) }}">
|
href="{{ chill_path_add_return_path('chill_calendar_calendar_to_activity', { 'id': calendar.id }) }}">
|
||||||
|
@ -9,13 +9,13 @@
|
|||||||
{% block js %}
|
{% block js %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
{{ encore_entry_script_tags('mod_answer') }}
|
{{ encore_entry_script_tags('mod_answer') }}
|
||||||
{{ encore_entry_script_tags('mod_async_upload') }}
|
{{ encore_entry_script_tags('mod_document_action_buttons_group') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{{ parent() }}
|
{{ parent() }}
|
||||||
{{ encore_entry_link_tags('mod_answer') }}
|
{{ encore_entry_link_tags('mod_answer') }}
|
||||||
{{ encore_entry_link_tags('mod_async_upload') }}
|
{{ encore_entry_link_tags('mod_document_action_buttons_group') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
{{ form_start(form) }}
|
{{ form_start(form) }}
|
||||||
|
|
||||||
{{ form_row(form.title) }}
|
{{ form_row(form.title) }}
|
||||||
{{ form_row(form.doc) }}
|
|
||||||
|
|
||||||
<ul class="record_actions sticky-form-buttons">
|
<ul class="record_actions sticky-form-buttons">
|
||||||
<li class="cancel">
|
<li class="cancel">
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
{{ form_start(form) }}
|
{{ form_start(form) }}
|
||||||
|
|
||||||
{{ form_row(form.title) }}
|
{{ form_row(form.title) }}
|
||||||
{{ form_row(form.doc) }}
|
|
||||||
|
|
||||||
<ul class="record_actions sticky-form-buttons">
|
<ul class="record_actions sticky-form-buttons">
|
||||||
<li class="cancel">
|
<li class="cancel">
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
<ul class="record_actions sticky-form-buttons">
|
<ul class="record_actions sticky-form-buttons">
|
||||||
<li class="cancel">
|
<li class="cancel">
|
||||||
<a class="btn btn-cancel" href="{{ chill_return_path_or('chill_calendar_calendar_list_by_accompanying_period', {'id': accompanyingCourse.id }) }}">{{ 'Cancel'|trans|chill_return_path_label }}</a>
|
<a class="btn btn-cancel" href="{{ chill_return_path_or('chill_calendar_calendar_edit', {'id': calendar_doc.calendar.id }) }}">{{ 'Cancel'|trans|chill_return_path_label }}</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
|
@ -31,8 +31,6 @@ use Symfony\Component\Form\FormBuilderInterface;
|
|||||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||||
use function count;
|
use function count;
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
final class CalendarContext implements CalendarContextInterface
|
final class CalendarContext implements CalendarContextInterface
|
||||||
{
|
{
|
||||||
private BaseContextData $baseContextData;
|
private BaseContextData $baseContextData;
|
||||||
@ -150,10 +148,8 @@ final class CalendarContext implements CalendarContextInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* param array{mainPerson?: Person, thirdParty?: ThirdParty, title: string} $contextGenerationData
|
|
||||||
* @param mixed $entity
|
|
||||||
*/
|
*/
|
||||||
public function getData(DocGeneratorTemplate $template, $entity, array $contextGenerationData = []): array
|
public function getData(DocGeneratorTemplate $template, mixed $entity, array $contextGenerationData = []): array
|
||||||
{
|
{
|
||||||
$options = $this->getOptions($template);
|
$options = $this->getOptions($template);
|
||||||
|
|
||||||
@ -274,9 +270,6 @@ final class CalendarContext implements CalendarContextInterface
|
|||||||
return $denormalized;
|
return $denormalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* param array{mainPerson?: Person, thirdParty?: ThirdParty, title: string} $contextGenerationData
|
|
||||||
*/
|
|
||||||
public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void
|
public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void
|
||||||
{
|
{
|
||||||
$options = $this->getOptions($template);
|
$options = $this->getOptions($template);
|
||||||
@ -287,9 +280,6 @@ final class CalendarContext implements CalendarContextInterface
|
|||||||
$this->entityManager->persist($doc);
|
$this->entityManager->persist($doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* return array{askMainPerson: bool, mainPersonLabel: ?string, askThirdParty: bool, thirdPartyLabel: ?string, trackDateTime: bool} $options
|
|
||||||
*/
|
|
||||||
private function getOptions(DocGeneratorTemplate $template): array
|
private function getOptions(DocGeneratorTemplate $template): array
|
||||||
{
|
{
|
||||||
return $template->getOptions();
|
return $template->getOptions();
|
||||||
|
@ -12,6 +12,7 @@ declare(strict_types=1);
|
|||||||
namespace Chill\CalendarBundle\Service\DocGenerator;
|
namespace Chill\CalendarBundle\Service\DocGenerator;
|
||||||
|
|
||||||
use Chill\CalendarBundle\Entity\Calendar;
|
use Chill\CalendarBundle\Entity\Calendar;
|
||||||
|
use Chill\DocGeneratorBundle\Context\DocGeneratorContextInterface;
|
||||||
use Chill\DocGeneratorBundle\Context\DocGeneratorContextWithAdminFormInterface;
|
use Chill\DocGeneratorBundle\Context\DocGeneratorContextWithAdminFormInterface;
|
||||||
use Chill\DocGeneratorBundle\Context\DocGeneratorContextWithPublicFormInterface;
|
use Chill\DocGeneratorBundle\Context\DocGeneratorContextWithPublicFormInterface;
|
||||||
use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
|
use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
|
||||||
@ -19,37 +20,9 @@ use Chill\DocStoreBundle\Entity\StoredObject;
|
|||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template-extends DocGeneratorContextWithPublicFormInterface<Calendar>
|
* @extends DocGeneratorContextWithPublicFormInterface<Calendar>
|
||||||
|
* @extends DocGeneratorContextWithAdminFormInterface<Calendar>
|
||||||
*/
|
*/
|
||||||
interface CalendarContextInterface extends DocGeneratorContextWithPublicFormInterface, DocGeneratorContextWithAdminFormInterface
|
interface CalendarContextInterface extends DocGeneratorContextWithPublicFormInterface, DocGeneratorContextWithAdminFormInterface
|
||||||
{
|
{
|
||||||
public function adminFormReverseTransform(array $data): array;
|
|
||||||
|
|
||||||
public function adminFormTransform(array $data): array;
|
|
||||||
|
|
||||||
public function buildAdminForm(FormBuilderInterface $builder): void;
|
|
||||||
|
|
||||||
public function buildPublicForm(FormBuilderInterface $builder, DocGeneratorTemplate $template, $entity): void;
|
|
||||||
|
|
||||||
public function getData(DocGeneratorTemplate $template, $entity, array $contextGenerationData = []): array;
|
|
||||||
|
|
||||||
public function getDescription(): string;
|
|
||||||
|
|
||||||
public function getEntityClass(): string;
|
|
||||||
|
|
||||||
public function getFormData(DocGeneratorTemplate $template, $entity): array;
|
|
||||||
|
|
||||||
public static function getKey(): string;
|
|
||||||
|
|
||||||
public function getName(): string;
|
|
||||||
|
|
||||||
public function hasAdminForm(): bool;
|
|
||||||
|
|
||||||
public function hasPublicForm(DocGeneratorTemplate $template, $entity): bool;
|
|
||||||
|
|
||||||
public function contextGenerationDataNormalize(DocGeneratorTemplate $template, $entity, array $data): array;
|
|
||||||
|
|
||||||
public function contextGenerationDataDenormalize(DocGeneratorTemplate $template, $entity, array $data): array;
|
|
||||||
|
|
||||||
public function storeGenerated(DocGeneratorTemplate $template, StoredObject $storedObject, object $entity, array $contextGenerationData): void;
|
|
||||||
}
|
}
|
||||||
|
@ -132,8 +132,8 @@ docgen:
|
|||||||
Base context for calendar: 'Rendez-vous: contexte de base'
|
Base context for calendar: 'Rendez-vous: contexte de base'
|
||||||
A base context for generating document on calendar: Contexte pour générer des documents à partir des rendez-vous
|
A base context for generating document on calendar: Contexte pour générer des documents à partir des rendez-vous
|
||||||
Track changes on datetime and warn user if date time is updated after the doc generation: Suivre les changements sur le document et prévenir les utilisateurs que la date et l'heure ont été modifiée après la génération du document
|
Track changes on datetime and warn user if date time is updated after the doc generation: Suivre les changements sur le document et prévenir les utilisateurs que la date et l'heure ont été modifiée après la génération du document
|
||||||
Ask main person: Demander de choisir une personne parmi les participants aux rendez-vous
|
Ask main person: Demander de choisir un usager parmi les participants aux rendez-vous
|
||||||
Main person label: Label pour choisir la personne
|
Main person label: Label pour choisir l'usager
|
||||||
Ask third party: Demander de choisir un tiers parmi les participants aux rendez-vous
|
Ask third party: Demander de choisir un tiers parmi les participants aux rendez-vous
|
||||||
Third party label: Label pour choisir le tiers
|
Third party label: Label pour choisir le tiers
|
||||||
Destinee: Destinataire
|
Destinee: Destinataire
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
calendar:
|
calendar:
|
||||||
At least {{ limit }} person is required.: Au moins {{ limit }} personne doit être associée à ce rendez-vous
|
At least {{ limit }} person is required.: Au moins {{ limit }} usager doit être associée à ce rendez-vous
|
||||||
An end date is required: Indiquez une date et heure de fin
|
An end date is required: Indiquez une date et heure de fin
|
||||||
A start date is required: Indiquez une date et heure de début
|
A start date is required: Indiquez une date et heure de début
|
||||||
A location is required: Indiquez un lieu
|
A location is required: Indiquez un lieu
|
||||||
|
@ -13,6 +13,10 @@ namespace Chill\DocGeneratorBundle\Context;
|
|||||||
|
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T of object
|
||||||
|
* @extends DocGeneratorContextInterface<T>
|
||||||
|
*/
|
||||||
interface DocGeneratorContextWithAdminFormInterface extends DocGeneratorContextInterface
|
interface DocGeneratorContextWithAdminFormInterface extends DocGeneratorContextInterface
|
||||||
{
|
{
|
||||||
public function adminFormReverseTransform(array $data): array;
|
public function adminFormReverseTransform(array $data): array;
|
||||||
|
@ -15,7 +15,8 @@ use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
|
|||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template T
|
* @template T of object
|
||||||
|
* @extends DocGeneratorContextInterface<T>
|
||||||
*/
|
*/
|
||||||
interface DocGeneratorContextWithPublicFormInterface extends DocGeneratorContextInterface
|
interface DocGeneratorContextWithPublicFormInterface extends DocGeneratorContextInterface
|
||||||
{
|
{
|
||||||
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\DocStoreBundle\Entity;
|
namespace Chill\DocStoreBundle\Entity;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\HasCentersInterface;
|
||||||
use Chill\MainBundle\Entity\HasScopesInterface;
|
use Chill\MainBundle\Entity\HasScopesInterface;
|
||||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
@ -19,7 +20,7 @@ use Doctrine\ORM\Mapping as ORM;
|
|||||||
* @ORM\Entity
|
* @ORM\Entity
|
||||||
* @ORM\Table("chill_doc.accompanyingcourse_document")
|
* @ORM\Table("chill_doc.accompanyingcourse_document")
|
||||||
*/
|
*/
|
||||||
class AccompanyingCourseDocument extends Document implements HasScopesInterface
|
class AccompanyingCourseDocument extends Document implements HasScopesInterface, HasCentersInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class)
|
* @ORM\ManyToOne(targetEntity=AccompanyingPeriod::class)
|
||||||
@ -27,6 +28,11 @@ class AccompanyingCourseDocument extends Document implements HasScopesInterface
|
|||||||
*/
|
*/
|
||||||
private ?AccompanyingPeriod $course = null;
|
private ?AccompanyingPeriod $course = null;
|
||||||
|
|
||||||
|
public function getCenters(): ?iterable
|
||||||
|
{
|
||||||
|
return $this->course->getCenters();
|
||||||
|
}
|
||||||
|
|
||||||
public function getCourse(): ?AccompanyingPeriod
|
public function getCourse(): ?AccompanyingPeriod
|
||||||
{
|
{
|
||||||
return $this->course;
|
return $this->course;
|
||||||
|
@ -51,16 +51,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="item-col record_actions flex-shrink-1">
|
<ul class="item-col record_actions flex-shrink-1">
|
||||||
{% if document.course is defined %}
|
{% if document.course is defined %}
|
||||||
{% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_DELETE', document) %}
|
|
||||||
<li class="delete">
|
|
||||||
<a href="{{ chill_return_path_or('chill_docstore_accompanying_course_document_delete', {'course': accompanyingCourse.id, 'id': document.id}) }}" class="btn btn-delete"></a>
|
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_UPDATE', document) %}
|
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ path('accompanying_course_document_edit', {'course': accompanyingCourse.id, 'id': document.id }) }}" class="btn btn-update"></a>
|
{{ chill_entity_workflow_list('Chill\\DocStoreBundle\\Entity\\AccompanyingCourseDocument', document.id) }}
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
|
||||||
{% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_SEE_DETAILS', document) %}
|
{% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_SEE_DETAILS', document) %}
|
||||||
<li>
|
<li>
|
||||||
{{ document.object|chill_document_button_group(document.title, is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_UPDATE', document)) }}
|
{{ document.object|chill_document_button_group(document.title, is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_UPDATE', document)) }}
|
||||||
@ -69,20 +62,17 @@
|
|||||||
<a href="{{ chill_path_add_return_path('accompanying_course_document_show', {'course': accompanyingCourse.id, 'id': document.id}) }}" class="btn btn-show"></a>
|
<a href="{{ chill_path_add_return_path('accompanying_course_document_show', {'course': accompanyingCourse.id, 'id': document.id}) }}" class="btn btn-show"></a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_UPDATE', document) %}
|
||||||
<li>
|
<li>
|
||||||
{{ chill_entity_workflow_list('Chill\\DocStoreBundle\\Entity\\AccompanyingCourseDocument', document.id) }}
|
<a href="{{ path('accompanying_course_document_edit', {'course': accompanyingCourse.id, 'id': document.id }) }}" class="btn btn-update"></a>
|
||||||
</li>
|
</li>
|
||||||
{% else %}
|
{% endif %}
|
||||||
{% if is_granted('CHILL_PERSON_DOCUMENT_DELETE', document) %}
|
{% if is_granted('CHILL_ACCOMPANYING_COURSE_DOCUMENT_DELETE', document) %}
|
||||||
<li class="delete">
|
<li class="delete">
|
||||||
<a href="{{ chill_return_path_or('chill_docstore_person_document_delete', {'person': person.id, 'id': document.id}) }}" class="btn btn-delete"></a>
|
<a href="{{ chill_return_path_or('chill_docstore_accompanying_course_document_delete', {'course': accompanyingCourse.id, 'id': document.id}) }}" class="btn btn-delete"></a>
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% if is_granted('CHILL_PERSON_DOCUMENT_UPDATE', document) %}
|
|
||||||
<li>
|
|
||||||
<a href="{{ path('person_document_edit', {'person': person.id, 'id': document.id}) }}" class="btn btn-update"></a>
|
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
{% if is_granted('CHILL_PERSON_DOCUMENT_SEE_DETAILS', document) %}
|
{% if is_granted('CHILL_PERSON_DOCUMENT_SEE_DETAILS', document) %}
|
||||||
<li>
|
<li>
|
||||||
{{ document.object|chill_document_button_group(document.title, is_granted('CHILL_PERSON_DOCUMENT_UPDATE', document)) }}
|
{{ document.object|chill_document_button_group(document.title, is_granted('CHILL_PERSON_DOCUMENT_UPDATE', document)) }}
|
||||||
@ -91,6 +81,16 @@
|
|||||||
<a href="{{ path('person_document_show', {'person': person.id, 'id': document.id}) }}" class="btn btn-show"></a>
|
<a href="{{ path('person_document_show', {'person': person.id, 'id': document.id}) }}" class="btn btn-show"></a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if is_granted('CHILL_PERSON_DOCUMENT_UPDATE', document) %}
|
||||||
|
<li>
|
||||||
|
<a href="{{ path('person_document_edit', {'person': person.id, 'id': document.id}) }}" class="btn btn-update"></a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
|
{% if is_granted('CHILL_PERSON_DOCUMENT_DELETE', document) %}
|
||||||
|
<li class="delete">
|
||||||
|
<a href="{{ chill_return_path_or('chill_docstore_person_document_delete', {'person': person.id, 'id': document.id}) }}" class="btn btn-delete"></a>
|
||||||
|
</li>
|
||||||
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -78,12 +78,12 @@ class AccompanyingCourseDocumentVoter extends AbstractChillVoter implements Prov
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function supports($attribute, $subject)
|
protected function supports($attribute, $subject): bool
|
||||||
{
|
{
|
||||||
return $this->voterHelper->supports($attribute, $subject);
|
return $this->voterHelper->supports($attribute, $subject);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
|
protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
|
||||||
{
|
{
|
||||||
if (!$token->getUser() instanceof User) {
|
if (!$token->getUser() instanceof User) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -113,8 +113,7 @@ class EventSearch extends AbstractSearch
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// format is "json"
|
||||||
if ('json' === $format) {
|
|
||||||
$results = [];
|
$results = [];
|
||||||
$search = $this->search($terms, $start, $limit, $options);
|
$search = $this->search($terms, $start, $limit, $options);
|
||||||
|
|
||||||
@ -129,12 +128,9 @@ class EventSearch extends AbstractSearch
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'results' => $results,
|
'results' => $results,
|
||||||
'pagination' => [
|
|
||||||
'more' => $paginator->hasNextPage(),
|
'more' => $paginator->hasNextPage(),
|
||||||
],
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public function supports($domain, $format)
|
public function supports($domain, $format)
|
||||||
{
|
{
|
||||||
|
@ -34,7 +34,7 @@ Edit the participation: Modifier la participation
|
|||||||
Participation Edit: Modifier une participation
|
Participation Edit: Modifier une participation
|
||||||
Add a participation: Ajouter un participant
|
Add a participation: Ajouter un participant
|
||||||
Participation creation: Ajouter une participation
|
Participation creation: Ajouter une participation
|
||||||
Associated person: Personne associée
|
Associated person: Usager associé
|
||||||
Associated event: Événement associé
|
Associated event: Événement associé
|
||||||
Back to the event: Retour à l'événement
|
Back to the event: Retour à l'événement
|
||||||
The participation was created: La participation a été créée
|
The participation was created: La participation a été créée
|
||||||
|
@ -0,0 +1,111 @@
|
|||||||
|
<?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\MainBundle\Controller;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||||
|
use Symfony\Component\Serializer\SerializerInterface;
|
||||||
|
|
||||||
|
class AddressToReferenceMatcherController
|
||||||
|
{
|
||||||
|
private Security $security;
|
||||||
|
|
||||||
|
private EntityManagerInterface $entityManager;
|
||||||
|
|
||||||
|
private SerializerInterface $serializer;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
Security $security,
|
||||||
|
EntityManagerInterface $entityManager,
|
||||||
|
SerializerInterface $serializer
|
||||||
|
) {
|
||||||
|
$this->security = $security;
|
||||||
|
$this->entityManager = $entityManager;
|
||||||
|
$this->serializer = $serializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/api/1.0/main/address/reference-match/{id}/set/reviewed", methods={"POST"})
|
||||||
|
*/
|
||||||
|
public function markAddressAsReviewed(Address $address): JsonResponse
|
||||||
|
{
|
||||||
|
if (!$this->security->isGranted('ROLE_USER')) {
|
||||||
|
throw new AccessDeniedHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$address->setRefStatus(Address::ADDR_REFERENCE_STATUS_REVIEWED);
|
||||||
|
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
return new JsonResponse(
|
||||||
|
$this->serializer->serialize($address, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||||
|
JsonResponse::HTTP_OK,
|
||||||
|
[],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an address back to "to review". Only if the address is in "reviewed" state.
|
||||||
|
*
|
||||||
|
* @Route("/api/1.0/main/address/reference-match/{id}/set/to_review", methods={"POST"})
|
||||||
|
*/
|
||||||
|
public function markAddressAsToReview(Address $address): JsonResponse
|
||||||
|
{
|
||||||
|
if (!$this->security->isGranted('ROLE_USER')) {
|
||||||
|
throw new AccessDeniedHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Address::ADDR_REFERENCE_STATUS_REVIEWED !== $address->getRefStatus()) {
|
||||||
|
throw new AccessDeniedHttpException("forbidden to mark a matching address to 'to review'");
|
||||||
|
}
|
||||||
|
|
||||||
|
$address->setRefStatus(Address::ADDR_REFERENCE_STATUS_TO_REVIEW);
|
||||||
|
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
return new JsonResponse(
|
||||||
|
$this->serializer->serialize($address, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||||
|
JsonResponse::HTTP_OK,
|
||||||
|
[],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/api/1.0/main/address/reference-match/{id}/sync-with-reference", methods={"POST"})
|
||||||
|
*/
|
||||||
|
public function syncAddressWithReference(Address $address): JsonResponse
|
||||||
|
{
|
||||||
|
if (null === $address->getAddressReference()) {
|
||||||
|
throw new BadRequestHttpException('this address does not have any address reference');
|
||||||
|
}
|
||||||
|
|
||||||
|
$address->syncWithReference($address->getAddressReference());
|
||||||
|
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
return new JsonResponse(
|
||||||
|
$this->serializer->serialize($address, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||||
|
JsonResponse::HTTP_OK,
|
||||||
|
[],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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\MainBundle\Controller;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||||
|
use Chill\MainBundle\Repository\GeographicalUnitRepositoryInterface;
|
||||||
|
use Chill\MainBundle\Serializer\Model\Collection;
|
||||||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||||
|
use Symfony\Component\Serializer\SerializerInterface;
|
||||||
|
|
||||||
|
class GeographicalUnitByAddressApiController
|
||||||
|
{
|
||||||
|
private PaginatorFactory $paginatorFactory;
|
||||||
|
|
||||||
|
private GeographicalUnitRepositoryInterface $geographicalUnitRepository;
|
||||||
|
|
||||||
|
private Security $security;
|
||||||
|
|
||||||
|
private SerializerInterface $serializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param PaginatorFactory $paginatorFactory
|
||||||
|
* @param GeographicalUnitRepositoryInterface $geographicalUnitRepository
|
||||||
|
* @param Security $security
|
||||||
|
* @param SerializerInterface $serializer
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
PaginatorFactory $paginatorFactory,
|
||||||
|
GeographicalUnitRepositoryInterface $geographicalUnitRepository,
|
||||||
|
Security $security,
|
||||||
|
SerializerInterface $serializer
|
||||||
|
) {
|
||||||
|
$this->paginatorFactory = $paginatorFactory;
|
||||||
|
$this->geographicalUnitRepository = $geographicalUnitRepository;
|
||||||
|
$this->security = $security;
|
||||||
|
$this->serializer = $serializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/api/1.0/main/geographical-unit/by-address/{id}.{_format}", requirements={"_format": "json"})
|
||||||
|
*/
|
||||||
|
public function getGeographicalUnitCoveringAddress(Address $address): JsonResponse
|
||||||
|
{
|
||||||
|
if (!$this->security->isGranted('ROLE_USER')) {
|
||||||
|
throw new AccessDeniedHttpException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$count = $this->geographicalUnitRepository->countGeographicalUnitContainingAddress($address);
|
||||||
|
$pagination = $this->paginatorFactory->create($count);
|
||||||
|
$units = $this->geographicalUnitRepository->findGeographicalUnitContainingAddress($address, $pagination->getCurrentPageFirstItemNumber(), $pagination->getItemsPerPage());
|
||||||
|
|
||||||
|
$collection = new Collection($units, $pagination);
|
||||||
|
|
||||||
|
return new JsonResponse(
|
||||||
|
$this->serializer->serialize($collection, 'json', [AbstractNormalizer::GROUPS => ['read']]),
|
||||||
|
JsonResponse::HTTP_OK,
|
||||||
|
[],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -46,6 +46,7 @@ use Chill\MainBundle\Doctrine\Type\NativeDateIntervalType;
|
|||||||
use Chill\MainBundle\Doctrine\Type\PointType;
|
use Chill\MainBundle\Doctrine\Type\PointType;
|
||||||
use Chill\MainBundle\Entity\Civility;
|
use Chill\MainBundle\Entity\Civility;
|
||||||
use Chill\MainBundle\Entity\Country;
|
use Chill\MainBundle\Entity\Country;
|
||||||
|
use Chill\MainBundle\Entity\GeographicalUnitLayer;
|
||||||
use Chill\MainBundle\Entity\Language;
|
use Chill\MainBundle\Entity\Language;
|
||||||
use Chill\MainBundle\Entity\Location;
|
use Chill\MainBundle\Entity\Location;
|
||||||
use Chill\MainBundle\Entity\LocationType;
|
use Chill\MainBundle\Entity\LocationType;
|
||||||
@ -732,6 +733,20 @@ class ChillMainExtension extends Extension implements
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'class' => GeographicalUnitLayer::class,
|
||||||
|
'name' => 'geographical-unit-layer',
|
||||||
|
'base_path' => '/api/1.0/main/geographical-unit-layer',
|
||||||
|
'base_role' => 'ROLE_USER',
|
||||||
|
'actions' => [
|
||||||
|
'_index' => [
|
||||||
|
'methods' => [
|
||||||
|
Request::METHOD_GET => true,
|
||||||
|
Request::METHOD_HEAD => true,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ trait AddWidgetConfigurationTrait
|
|||||||
*
|
*
|
||||||
* @throws InvalidConfigurationException if a service's tag does not have the "alias" key
|
* @throws InvalidConfigurationException if a service's tag does not have the "alias" key
|
||||||
*
|
*
|
||||||
* @return type
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function getWidgetAliasesbyPlace($place, ContainerBuilder $containerBuilder)
|
protected function getWidgetAliasesbyPlace($place, ContainerBuilder $containerBuilder)
|
||||||
{
|
{
|
||||||
|
@ -31,9 +31,6 @@ class NativeDateIntervalType extends DateIntervalType
|
|||||||
{
|
{
|
||||||
public const FORMAT = '%rP%YY%MM%DDT%HH%IM%SS';
|
public const FORMAT = '%rP%YY%MM%DDT%HH%IM%SS';
|
||||||
|
|
||||||
/**
|
|
||||||
* @param DateInterval|null $value
|
|
||||||
*/
|
|
||||||
public function convertToDatabaseValue($value, AbstractPlatform $platform)
|
public function convertToDatabaseValue($value, AbstractPlatform $platform)
|
||||||
{
|
{
|
||||||
if (null === $value) {
|
if (null === $value) {
|
||||||
|
@ -12,6 +12,10 @@ declare(strict_types=1);
|
|||||||
namespace Chill\MainBundle\Entity;
|
namespace Chill\MainBundle\Entity;
|
||||||
|
|
||||||
use Chill\MainBundle\Doctrine\Model\Point;
|
use Chill\MainBundle\Doctrine\Model\Point;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackCreationTrait;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
|
||||||
|
use Chill\MainBundle\Doctrine\Model\TrackUpdateTrait;
|
||||||
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use DateTimeInterface;
|
use DateTimeInterface;
|
||||||
@ -28,8 +32,28 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
|||||||
* @ORM\Table(name="chill_main_address")
|
* @ORM\Table(name="chill_main_address")
|
||||||
* @ORM\HasLifecycleCallbacks
|
* @ORM\HasLifecycleCallbacks
|
||||||
*/
|
*/
|
||||||
class Address
|
class Address implements TrackCreationInterface, TrackUpdateInterface
|
||||||
{
|
{
|
||||||
|
use TrackCreationTrait;
|
||||||
|
use TrackUpdateTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When an Address does match with the AddressReference
|
||||||
|
*/
|
||||||
|
public const ADDR_REFERENCE_STATUS_MATCH = 'match';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When an Address does not match with the AddressReference, and
|
||||||
|
* is pending for a review
|
||||||
|
*/
|
||||||
|
public const ADDR_REFERENCE_STATUS_TO_REVIEW = 'to_review';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When an Address does not match with the AddressReference, but
|
||||||
|
* is reviewed
|
||||||
|
*/
|
||||||
|
public const ADDR_REFERENCE_STATUS_REVIEWED = 'reviewed';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\ManyToOne(targetEntity=AddressReference::class)
|
* @ORM\ManyToOne(targetEntity=AddressReference::class)
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
@ -37,67 +61,48 @@ class Address
|
|||||||
private ?AddressReference $addressReference = null;
|
private ?AddressReference $addressReference = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string|null
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $buildingName;
|
private string $buildingName = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="boolean")
|
* @ORM\Column(type="boolean", options={"default": false})
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private bool $confidential = false;
|
private bool $confidential = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string|null
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $corridor;
|
private string $corridor = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of metadata, added by customizable fields.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
private $customs = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string|null
|
|
||||||
*
|
|
||||||
* used for the CEDEX information
|
* used for the CEDEX information
|
||||||
*
|
*
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $distribution;
|
private string $distribution = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string|null
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $extra;
|
private string $extra = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string|null
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $flat;
|
private string $flat = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string|null
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $floor;
|
private string $floor = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of geographical units and addresses.
|
* List of geographical units and addresses.
|
||||||
@ -131,11 +136,9 @@ class Address
|
|||||||
* True if the address is a "no address", aka homeless person, ...
|
* True if the address is a "no address", aka homeless person, ...
|
||||||
*
|
*
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
* @ORM\Column(type="boolean")
|
* @ORM\Column(type="boolean", options={"default": false})
|
||||||
*
|
|
||||||
* @var bool
|
|
||||||
*/
|
*/
|
||||||
private $isNoAddress = false;
|
private bool $isNoAddress = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A ThirdParty reference for person's addresses that are linked to a third party.
|
* A ThirdParty reference for person's addresses that are linked to a third party.
|
||||||
@ -146,7 +149,7 @@ class Address
|
|||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
|
* @ORM\JoinColumn(nullable=true, onDelete="SET NULL")
|
||||||
*/
|
*/
|
||||||
private $linkedToThirdParty;
|
private ?ThirdParty $linkedToThirdParty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A geospatial field storing the coordinates of the Address.
|
* A geospatial field storing the coordinates of the Address.
|
||||||
@ -156,7 +159,7 @@ class Address
|
|||||||
* @ORM\Column(type="point", nullable=true)
|
* @ORM\Column(type="point", nullable=true)
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $point;
|
private ?Point $point = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\PostalCode")
|
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\PostalCode")
|
||||||
@ -166,28 +169,36 @@ class Address
|
|||||||
private ?PostalCode $postcode = null;
|
private ?PostalCode $postcode = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string|null
|
* @var self::ADDR_REFERENCE_STATUS_*
|
||||||
*
|
* @ORM\Column(type="text", nullable=false, options={"default": self::ADDR_REFERENCE_STATUS_MATCH})
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
|
||||||
* @Groups({"write"})
|
|
||||||
*/
|
*/
|
||||||
private $steps;
|
private string $refStatus = self::ADDR_REFERENCE_STATUS_MATCH;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @ORM\Column(type="datetime_immutable", nullable=false, options={"default": "CURRENT_TIMESTAMP"})
|
||||||
*
|
|
||||||
* @ORM\Column(type="string", length=255)
|
|
||||||
* @Groups({"write"})
|
|
||||||
*/
|
*/
|
||||||
private $street = '';
|
private \DateTimeImmutable $refStatusLastUpdate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
|
||||||
*
|
*
|
||||||
* @ORM\Column(type="string", length=255)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @Groups({"write"})
|
* @Groups({"write"})
|
||||||
*/
|
*/
|
||||||
private $streetNumber = '';
|
private string $steps = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
|
* @Groups({"write"})
|
||||||
|
*/
|
||||||
|
private string $street = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
|
* @Groups({"write"})
|
||||||
|
*/
|
||||||
|
private string $streetNumber = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates when the address starts validation. Used to build an history
|
* Indicates when the address starts validation. Used to build an history
|
||||||
@ -210,6 +221,7 @@ class Address
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->validFrom = new DateTime();
|
$this->validFrom = new DateTime();
|
||||||
|
$this->refStatusLastUpdate = new \DateTimeImmutable('now');
|
||||||
$this->geographicalUnits = new ArrayCollection();
|
$this->geographicalUnits = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +232,6 @@ class Address
|
|||||||
->setBuildingName($original->getBuildingName())
|
->setBuildingName($original->getBuildingName())
|
||||||
->setConfidential($original->getConfidential())
|
->setConfidential($original->getConfidential())
|
||||||
->setCorridor($original->getCorridor())
|
->setCorridor($original->getCorridor())
|
||||||
->setCustoms($original->getCustoms())
|
|
||||||
->setDistribution($original->getDistribution())
|
->setDistribution($original->getDistribution())
|
||||||
->setExtra($original->getExtra())
|
->setExtra($original->getExtra())
|
||||||
->setFlat($original->getFlat())
|
->setFlat($original->getFlat())
|
||||||
@ -239,11 +250,20 @@ class Address
|
|||||||
public static function createFromAddressReference(AddressReference $original): Address
|
public static function createFromAddressReference(AddressReference $original): Address
|
||||||
{
|
{
|
||||||
return (new Address())
|
return (new Address())
|
||||||
->setPoint($original->getPoint())
|
->syncWithReference($original);
|
||||||
->setPostcode($original->getPostcode())
|
}
|
||||||
->setStreet($original->getStreet())
|
|
||||||
->setStreetNumber($original->getStreetNumber())
|
public function syncWithReference(AddressReference $addressReference): Address
|
||||||
->setAddressReference($original);
|
{
|
||||||
|
$this
|
||||||
|
->setPoint($addressReference->getPoint())
|
||||||
|
->setPostcode($addressReference->getPostcode())
|
||||||
|
->setStreet($addressReference->getStreet())
|
||||||
|
->setStreetNumber($addressReference->getStreetNumber())
|
||||||
|
->setRefStatus(self::ADDR_REFERENCE_STATUS_MATCH)
|
||||||
|
->setAddressReference($addressReference);
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAddressReference(): ?AddressReference
|
public function getAddressReference(): ?AddressReference
|
||||||
@ -251,7 +271,7 @@ class Address
|
|||||||
return $this->addressReference;
|
return $this->addressReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBuildingName(): ?string
|
public function getBuildingName(): string
|
||||||
{
|
{
|
||||||
return $this->buildingName;
|
return $this->buildingName;
|
||||||
}
|
}
|
||||||
@ -261,35 +281,27 @@ class Address
|
|||||||
return $this->confidential;
|
return $this->confidential;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCorridor(): ?string
|
public function getCorridor(): string
|
||||||
{
|
{
|
||||||
return $this->corridor;
|
return $this->corridor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function getDistribution(): string
|
||||||
* Get customs informations in the address.
|
|
||||||
*/
|
|
||||||
public function getCustoms(): array
|
|
||||||
{
|
|
||||||
return $this->customs;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDistribution(): ?string
|
|
||||||
{
|
{
|
||||||
return $this->distribution;
|
return $this->distribution;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getExtra(): ?string
|
public function getExtra(): string
|
||||||
{
|
{
|
||||||
return $this->extra;
|
return $this->extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFlat(): ?string
|
public function getFlat(): string
|
||||||
{
|
{
|
||||||
return $this->flat;
|
return $this->flat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFloor(): ?string
|
public function getFloor(): string
|
||||||
{
|
{
|
||||||
return $this->floor;
|
return $this->floor;
|
||||||
}
|
}
|
||||||
@ -340,12 +352,22 @@ class Address
|
|||||||
return $this->postcode;
|
return $this->postcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSteps(): ?string
|
public function getRefStatus(): string
|
||||||
|
{
|
||||||
|
return $this->refStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRefStatusLastUpdate(): \DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->refStatusLastUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSteps(): string
|
||||||
{
|
{
|
||||||
return $this->steps;
|
return $this->steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStreet(): ?string
|
public function getStreet(): string
|
||||||
{
|
{
|
||||||
return $this->street;
|
return $this->street;
|
||||||
}
|
}
|
||||||
@ -354,6 +376,7 @@ class Address
|
|||||||
* Get streetAddress1 (legacy function).
|
* Get streetAddress1 (legacy function).
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function getStreetAddress1()
|
public function getStreetAddress1()
|
||||||
{
|
{
|
||||||
@ -364,13 +387,14 @@ class Address
|
|||||||
* Get streetAddress2 (legacy function).
|
* Get streetAddress2 (legacy function).
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function getStreetAddress2()
|
public function getStreetAddress2()
|
||||||
{
|
{
|
||||||
return $this->streetNumber;
|
return $this->streetNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStreetNumber(): ?string
|
public function getStreetNumber(): string
|
||||||
{
|
{
|
||||||
return $this->streetNumber;
|
return $this->streetNumber;
|
||||||
}
|
}
|
||||||
@ -378,7 +402,7 @@ class Address
|
|||||||
/**
|
/**
|
||||||
* @return DateTime
|
* @return DateTime
|
||||||
*/
|
*/
|
||||||
public function getValidFrom()
|
public function getValidFrom(): DateTime
|
||||||
{
|
{
|
||||||
return $this->validFrom;
|
return $this->validFrom;
|
||||||
}
|
}
|
||||||
@ -407,7 +431,7 @@ class Address
|
|||||||
|
|
||||||
public function setBuildingName(?string $buildingName): self
|
public function setBuildingName(?string $buildingName): self
|
||||||
{
|
{
|
||||||
$this->buildingName = $buildingName;
|
$this->buildingName = (string) $buildingName;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -421,47 +445,35 @@ class Address
|
|||||||
|
|
||||||
public function setCorridor(?string $corridor): self
|
public function setCorridor(?string $corridor): self
|
||||||
{
|
{
|
||||||
$this->corridor = $corridor;
|
$this->corridor = (string) $corridor;
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store custom informations in the address.
|
|
||||||
*
|
|
||||||
* @return $this
|
|
||||||
*/
|
|
||||||
public function setCustoms(array $customs): self
|
|
||||||
{
|
|
||||||
$this->customs = $customs;
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setDistribution(?string $distribution): self
|
public function setDistribution(?string $distribution): self
|
||||||
{
|
{
|
||||||
$this->distribution = $distribution;
|
$this->distribution = (string) $distribution;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setExtra(?string $extra): self
|
public function setExtra(?string $extra): self
|
||||||
{
|
{
|
||||||
$this->extra = $extra;
|
$this->extra = (string) $extra;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setFlat(?string $flat): self
|
public function setFlat(?string $flat): self
|
||||||
{
|
{
|
||||||
$this->flat = $flat;
|
$this->flat = (string) $flat;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setFloor(?string $floor): self
|
public function setFloor(?string $floor): self
|
||||||
{
|
{
|
||||||
$this->floor = $floor;
|
$this->floor = (string) $floor;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -508,19 +520,44 @@ class Address
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the ref status
|
||||||
|
*
|
||||||
|
* <<<<<<< HEAD
|
||||||
|
* @param Address::ADDR_REFERENCE_STATUS_* $refStatus
|
||||||
|
* @param bool|null $updateLastUpdate Also update the "refStatusLastUpdate"
|
||||||
|
* =======
|
||||||
|
* The refstatuslast update is also updated
|
||||||
|
* >>>>>>> 31152616d (Feature: Provide api endpoint for reviewing addresses)
|
||||||
|
*/
|
||||||
|
public function setRefStatus(string $refStatus, ?bool $updateLastUpdate = true): self
|
||||||
|
{
|
||||||
|
$this->refStatus = $refStatus;
|
||||||
|
|
||||||
|
if ($updateLastUpdate) {
|
||||||
|
$this->setRefStatusLastUpdate(new \DateTimeImmutable('now'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRefStatusLastUpdate(\DateTimeImmutable $refStatusLastUpdate): self
|
||||||
|
{
|
||||||
|
$this->refStatusLastUpdate = $refStatusLastUpdate;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function setSteps(?string $steps): self
|
public function setSteps(?string $steps): self
|
||||||
{
|
{
|
||||||
$this->steps = $steps;
|
$this->steps = (string) $steps;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setStreet(?string $street): self
|
public function setStreet(?string $street): self
|
||||||
{
|
{
|
||||||
if (null === $street) {
|
$this->street = (string) $street;
|
||||||
$street = '';
|
|
||||||
}
|
|
||||||
$this->street = $street;
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -531,6 +568,7 @@ class Address
|
|||||||
* @param string $streetAddress1
|
* @param string $streetAddress1
|
||||||
*
|
*
|
||||||
* @return Address
|
* @return Address
|
||||||
|
* @deprecated
|
||||||
*/
|
*/
|
||||||
public function setStreetAddress1($streetAddress1)
|
public function setStreetAddress1($streetAddress1)
|
||||||
{
|
{
|
||||||
@ -543,7 +581,7 @@ class Address
|
|||||||
* Set streetAddress2 (legacy function).
|
* Set streetAddress2 (legacy function).
|
||||||
*
|
*
|
||||||
* @param string $streetAddress2
|
* @param string $streetAddress2
|
||||||
*
|
* @deprecated
|
||||||
* @return Address
|
* @return Address
|
||||||
*/
|
*/
|
||||||
public function setStreetAddress2($streetAddress2)
|
public function setStreetAddress2($streetAddress2)
|
||||||
@ -555,10 +593,7 @@ class Address
|
|||||||
|
|
||||||
public function setStreetNumber(?string $streetNumber): self
|
public function setStreetNumber(?string $streetNumber): self
|
||||||
{
|
{
|
||||||
if (null === $streetNumber) {
|
$this->streetNumber = (string) $streetNumber;
|
||||||
$streetNumber = '';
|
|
||||||
}
|
|
||||||
$this->streetNumber = $streetNumber;
|
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -605,7 +640,7 @@ class Address
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($this->getStreetAddress1())) {
|
if ('' === $this->getStreet()) {
|
||||||
$context
|
$context
|
||||||
->buildViolation('address.street1-should-be-set')
|
->buildViolation('address.street1-should-be-set')
|
||||||
->atPath('streetAddress1')
|
->atPath('streetAddress1')
|
||||||
|
@ -55,13 +55,13 @@ class AddressReference
|
|||||||
* @ORM\Column(type="integer")
|
* @ORM\Column(type="integer")
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $id;
|
private ?int $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $municipalityCode;
|
private string $municipalityCode = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A geospatial field storing the coordinates of the Address.
|
* A geospatial field storing the coordinates of the Address.
|
||||||
@ -71,7 +71,7 @@ class AddressReference
|
|||||||
* @ORM\Column(type="point")
|
* @ORM\Column(type="point")
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $point;
|
private ?Point $point = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var PostalCode
|
* @var PostalCode
|
||||||
@ -79,31 +79,31 @@ class AddressReference
|
|||||||
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\PostalCode")
|
* @ORM\ManyToOne(targetEntity="Chill\MainBundle\Entity\PostalCode")
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $postcode;
|
private ?PostalCode $postcode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string", length=255)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $refId;
|
private string $refId = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $source;
|
private string $source = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $street;
|
private string $street = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
* @groups({"read"})
|
* @groups({"read"})
|
||||||
*/
|
*/
|
||||||
private $streetNumber;
|
private string $streetNumber = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="datetime_immutable", nullable=true)
|
* @ORM\Column(type="datetime_immutable", nullable=true)
|
||||||
@ -126,7 +126,7 @@ class AddressReference
|
|||||||
return $this->id;
|
return $this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMunicipalityCode(): ?string
|
public function getMunicipalityCode(): string
|
||||||
{
|
{
|
||||||
return $this->municipalityCode;
|
return $this->municipalityCode;
|
||||||
}
|
}
|
||||||
@ -141,27 +141,27 @@ class AddressReference
|
|||||||
*
|
*
|
||||||
* @return PostalCode
|
* @return PostalCode
|
||||||
*/
|
*/
|
||||||
public function getPostcode()
|
public function getPostcode(): ?PostalCode
|
||||||
{
|
{
|
||||||
return $this->postcode;
|
return $this->postcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRefId(): ?string
|
public function getRefId(): string
|
||||||
{
|
{
|
||||||
return $this->refId;
|
return $this->refId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSource(): ?string
|
public function getSource(): string
|
||||||
{
|
{
|
||||||
return $this->source;
|
return $this->source;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStreet(): ?string
|
public function getStreet(): string
|
||||||
{
|
{
|
||||||
return $this->street;
|
return $this->street;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getStreetNumber(): ?string
|
public function getStreetNumber(): string
|
||||||
{
|
{
|
||||||
return $this->streetNumber;
|
return $this->streetNumber;
|
||||||
}
|
}
|
||||||
@ -192,7 +192,7 @@ class AddressReference
|
|||||||
|
|
||||||
public function setMunicipalityCode(?string $municipalityCode): self
|
public function setMunicipalityCode(?string $municipalityCode): self
|
||||||
{
|
{
|
||||||
$this->municipalityCode = $municipalityCode;
|
$this->municipalityCode = (string) $municipalityCode;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@ -227,21 +227,21 @@ class AddressReference
|
|||||||
|
|
||||||
public function setSource(?string $source): self
|
public function setSource(?string $source): self
|
||||||
{
|
{
|
||||||
$this->source = $source;
|
$this->source = (string) $source;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setStreet(?string $street): self
|
public function setStreet(?string $street): self
|
||||||
{
|
{
|
||||||
$this->street = $street;
|
$this->street = (string) $street;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setStreetNumber(?string $streetNumber): self
|
public function setStreetNumber(?string $streetNumber): self
|
||||||
{
|
{
|
||||||
$this->streetNumber = $streetNumber;
|
$this->streetNumber = (string) $streetNumber;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\MainBundle\Entity\GeographicalUnit;
|
namespace Chill\MainBundle\Entity\GeographicalUnit;
|
||||||
|
|
||||||
|
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple GeographialUnit Data Transfer Object.
|
* Simple GeographialUnit Data Transfer Object.
|
||||||
*
|
*
|
||||||
@ -21,24 +23,28 @@ class SimpleGeographicalUnitDTO
|
|||||||
/**
|
/**
|
||||||
* @readonly
|
* @readonly
|
||||||
* @psalm-readonly
|
* @psalm-readonly
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
public int $id;
|
public int $id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @readonly
|
* @readonly
|
||||||
* @psalm-readonly
|
* @psalm-readonly
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
public int $layerId;
|
public int $layerId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @readonly
|
* @readonly
|
||||||
* @psalm-readonly
|
* @psalm-readonly
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
public string $unitName;
|
public string $unitName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @readonly
|
* @readonly
|
||||||
* @psalm-readonly
|
* @psalm-readonly
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
public string $unitRefId;
|
public string $unitRefId;
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ namespace Chill\MainBundle\Entity;
|
|||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Table(name="chill_main_geographical_unit_layer", uniqueConstraints={
|
* @ORM\Table(name="chill_main_geographical_unit_layer", uniqueConstraints={
|
||||||
@ -27,16 +28,19 @@ class GeographicalUnitLayer
|
|||||||
* @ORM\Id
|
* @ORM\Id
|
||||||
* @ORM\GeneratedValue
|
* @ORM\GeneratedValue
|
||||||
* @ORM\Column(type="integer")
|
* @ORM\Column(type="integer")
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
private ?int $id = null;
|
private ?int $id = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="json", nullable=false, options={"default": "[]"})
|
* @ORM\Column(type="json", nullable=false, options={"default": "[]"})
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
private array $name = [];
|
private array $name = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
* @ORM\Column(type="text", nullable=false, options={"default": ""})
|
||||||
|
* @Serializer\Groups({"read"})
|
||||||
*/
|
*/
|
||||||
private string $refId = '';
|
private string $refId = '';
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\MainBundle\Export;
|
namespace Chill\MainBundle\Export;
|
||||||
|
|
||||||
|
use Doctrine\ORM\NativeQuery;
|
||||||
use Doctrine\ORM\QueryBuilder;
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,6 +24,7 @@ use Doctrine\ORM\QueryBuilder;
|
|||||||
* aggregation, use `ListInterface`.
|
* aggregation, use `ListInterface`.
|
||||||
*
|
*
|
||||||
* @example Chill\PersonBundle\Export\CountPerson an example of implementation
|
* @example Chill\PersonBundle\Export\CountPerson an example of implementation
|
||||||
|
* @template Q of QueryBuilder|NativeQuery
|
||||||
*/
|
*/
|
||||||
interface ExportInterface extends ExportElementInterface
|
interface ExportInterface extends ExportElementInterface
|
||||||
{
|
{
|
||||||
@ -84,7 +86,7 @@ interface ExportInterface extends ExportElementInterface
|
|||||||
* @param mixed[] $values The values from the result. if there are duplicates, those might be given twice. Example: array('FR', 'BE', 'CZ', 'FR', 'BE', 'FR')
|
* @param mixed[] $values The values from the result. if there are duplicates, those might be given twice. Example: array('FR', 'BE', 'CZ', 'FR', 'BE', 'FR')
|
||||||
* @param mixed $data The data from the export's form (as defined in `buildForm`)
|
* @param mixed $data The data from the export's form (as defined in `buildForm`)
|
||||||
*
|
*
|
||||||
* @return pure-callable(null|string|int|float|'_header' $value):string|int|\DateTimeInterface where the first argument is the value, and the function should return the label to show in the formatted file. Example : `function($countryCode) use ($countries) { return $countries[$countryCode]->getName(); }`
|
* @return callable(null|string|int|float|'_header' $value): string|int|\DateTimeInterface where the first argument is the value, and the function should return the label to show in the formatted file. Example : `function($countryCode) use ($countries) { return $countries[$countryCode]->getName(); }`
|
||||||
*/
|
*/
|
||||||
public function getLabels($key, array $values, $data);
|
public function getLabels($key, array $values, $data);
|
||||||
|
|
||||||
@ -102,7 +104,7 @@ interface ExportInterface extends ExportElementInterface
|
|||||||
/**
|
/**
|
||||||
* Return the results of the query builder.
|
* Return the results of the query builder.
|
||||||
*
|
*
|
||||||
* @param \Doctrine\ORM\NativeQuery|QueryBuilder $query
|
* @param Q $query
|
||||||
* @param mixed[] $data the data from the export's fomr (added by self::buildForm)
|
* @param mixed[] $data the data from the export's fomr (added by self::buildForm)
|
||||||
*
|
*
|
||||||
* @return mixed[] an array of results
|
* @return mixed[] an array of results
|
||||||
@ -132,7 +134,7 @@ interface ExportInterface extends ExportElementInterface
|
|||||||
* @param array $acl an array where each row has a `center` key containing the Chill\MainBundle\Entity\Center, and `circles` keys containing the reachable circles. Example: `array( array('center' => $centerA, 'circles' => array($circleA, $circleB) ) )`
|
* @param array $acl an array where each row has a `center` key containing the Chill\MainBundle\Entity\Center, and `circles` keys containing the reachable circles. Example: `array( array('center' => $centerA, 'circles' => array($circleA, $circleB) ) )`
|
||||||
* @param array $data the data from the form, if any
|
* @param array $data the data from the form, if any
|
||||||
*
|
*
|
||||||
* @return \Doctrine\ORM\NativeQuery|QueryBuilder the query to execute.
|
* @return Q the query to execute.
|
||||||
*/
|
*/
|
||||||
public function initiateQuery(array $requiredModifiers, array $acl, array $data = []);
|
public function initiateQuery(array $requiredModifiers, array $acl, array $data = []);
|
||||||
|
|
||||||
|
@ -43,11 +43,13 @@ class AddressDataMapper implements DataMapperInterface
|
|||||||
/** @var FormInterface $form */
|
/** @var FormInterface $form */
|
||||||
switch ($key) {
|
switch ($key) {
|
||||||
case 'streetAddress1':
|
case 'streetAddress1':
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
$form->setData($address->getStreetAddress1());
|
$form->setData($address->getStreetAddress1());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'streetAddress2':
|
case 'streetAddress2':
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
$form->setData($address->getStreetAddress2());
|
$form->setData($address->getStreetAddress2());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -110,11 +112,13 @@ class AddressDataMapper implements DataMapperInterface
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
$address->setStreetAddress1($form->getData());
|
$address->setStreetAddress1($form->getData());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'streetAddress2':
|
case 'streetAddress2':
|
||||||
|
/** @phpstan-ignore-next-line */
|
||||||
$address->setStreetAddress2($form->getData());
|
$address->setStreetAddress2($form->getData());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -24,15 +24,7 @@ class ExportPickCenterDataMapper implements DataMapperInterface
|
|||||||
{
|
{
|
||||||
protected RegroupmentRepository $regroupmentRepository;
|
protected RegroupmentRepository $regroupmentRepository;
|
||||||
|
|
||||||
/**
|
public function mapDataToForms($data, $forms): void
|
||||||
* @param array|Center[] $data
|
|
||||||
* @param $forms
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function mapDataToForms($data, $forms)
|
|
||||||
{
|
{
|
||||||
if (null === $data) {
|
if (null === $data) {
|
||||||
return;
|
return;
|
||||||
@ -44,7 +36,9 @@ class ExportPickCenterDataMapper implements DataMapperInterface
|
|||||||
$pickedRegroupment = [];
|
$pickedRegroupment = [];
|
||||||
|
|
||||||
foreach ($this->regroupmentRepository->findAll() as $regroupment) {
|
foreach ($this->regroupmentRepository->findAll() as $regroupment) {
|
||||||
[$contained, $notContained] = $regroupment->getCenters()->partition(static function (Center $center) {
|
/** @phpstan-ignore-next-line */
|
||||||
|
[$contained, $notContained] = $regroupment->getCenters()->partition(static function (Center $center): bool {
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (0 === count($notContained)) {
|
if (0 === count($notContained)) {
|
||||||
@ -56,13 +50,7 @@ class ExportPickCenterDataMapper implements DataMapperInterface
|
|||||||
$form['centers']->setData($data);
|
$form['centers']->setData($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function mapFormsToData($forms, &$data): void
|
||||||
* @param iterable $forms
|
|
||||||
* @param array $data
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function mapFormsToData($forms, &$data)
|
|
||||||
{
|
{
|
||||||
/** @var array<string, FormInterface> $forms */
|
/** @var array<string, FormInterface> $forms */
|
||||||
$forms = iterator_to_array($forms);
|
$forms = iterator_to_array($forms);
|
||||||
@ -74,8 +62,8 @@ class ExportPickCenterDataMapper implements DataMapperInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (array_key_exists('regroupment', $forms)) {
|
if (array_key_exists('regroupment', $forms)) {
|
||||||
foreach ($forms['regroupment']->getData() as $regroupment) {
|
|
||||||
/** @var Regroupment $regroupment */
|
/** @var Regroupment $regroupment */
|
||||||
|
foreach ($forms['regroupment']->getData() as $regroupment) {
|
||||||
foreach ($regroupment->getCenters() as $center) {
|
foreach ($regroupment->getCenters() as $center) {
|
||||||
$centers[spl_object_hash($center)] = $center;
|
$centers[spl_object_hash($center)] = $center;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ class RollingDateDataMapper implements DataMapperInterface
|
|||||||
$forms = iterator_to_array($forms);
|
$forms = iterator_to_array($forms);
|
||||||
|
|
||||||
$viewData = new RollingDate(
|
$viewData = new RollingDate(
|
||||||
$forms['roll']->getData(),
|
($forms['roll']->getData() ?? RollingDate::T_TODAY),
|
||||||
$forms['fixedDate']->getData()
|
$forms['fixedDate']->getData()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,6 @@ class MultipleObjectsToIdTransformer implements DataTransformerInterface
|
|||||||
* Transforms a string (id) to an object (item).
|
* Transforms a string (id) to an object (item).
|
||||||
*
|
*
|
||||||
* @param mixed $array
|
* @param mixed $array
|
||||||
*
|
|
||||||
* @return ArrayCollection
|
|
||||||
*/
|
*/
|
||||||
public function reverseTransform($array)
|
public function reverseTransform($array)
|
||||||
{
|
{
|
||||||
@ -53,10 +51,8 @@ class MultipleObjectsToIdTransformer implements DataTransformerInterface
|
|||||||
* Transforms an object (use) to a string (id).
|
* Transforms an object (use) to a string (id).
|
||||||
*
|
*
|
||||||
* @param array $array
|
* @param array $array
|
||||||
*
|
|
||||||
* @return ArrayCollection
|
|
||||||
*/
|
*/
|
||||||
public function transform($array)
|
public function transform($array): array
|
||||||
{
|
{
|
||||||
$ret = [];
|
$ret = [];
|
||||||
|
|
||||||
|
@ -11,20 +11,58 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\MainBundle\Repository;
|
namespace Chill\MainBundle\Repository;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
use Chill\MainBundle\Entity\GeographicalUnit;
|
use Chill\MainBundle\Entity\GeographicalUnit;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\EntityRepository;
|
use Doctrine\ORM\EntityRepository;
|
||||||
|
use Doctrine\ORM\Query\Expr\Join;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
|
||||||
class GeographicalUnitRepository implements GeographicalUnitRepositoryInterface
|
final class GeographicalUnitRepository implements GeographicalUnitRepositoryInterface
|
||||||
{
|
{
|
||||||
private EntityManagerInterface $em;
|
|
||||||
|
|
||||||
private EntityRepository $repository;
|
private EntityRepository $repository;
|
||||||
|
|
||||||
public function __construct(EntityManagerInterface $em)
|
public function __construct(EntityManagerInterface $em)
|
||||||
{
|
{
|
||||||
$this->repository = $em->getRepository($this->getClassName());
|
$this->repository = $em->getRepository($this->getClassName());
|
||||||
$this->em = $em;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function countGeographicalUnitContainingAddress(Address $address): int
|
||||||
|
{
|
||||||
|
$qb = $this->buildQueryGeographicalUnitContainingAddress($address);
|
||||||
|
|
||||||
|
return $qb
|
||||||
|
->select('COUNT(gu)')
|
||||||
|
->getQuery()
|
||||||
|
->getSingleScalarResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findGeographicalUnitContainingAddress(Address $address, int $offset = 0, int $limit = 50): array
|
||||||
|
{
|
||||||
|
$qb = $this->buildQueryGeographicalUnitContainingAddress($address);
|
||||||
|
|
||||||
|
return $qb
|
||||||
|
->select(sprintf('NEW %s(gu.id, gu.unitName, gu.unitRefId, IDENTITY(gu.layer))', GeographicalUnit\SimpleGeographicalUnitDTO::class))
|
||||||
|
->addOrderBy('IDENTITY(gu.layer)')
|
||||||
|
->addOrderBy(('gu.unitName'))
|
||||||
|
->getQuery()
|
||||||
|
->setFirstResult($offset)
|
||||||
|
->setMaxResults($limit)
|
||||||
|
->getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildQueryGeographicalUnitContainingAddress(Address $address): QueryBuilder
|
||||||
|
{
|
||||||
|
$qb = $this->repository
|
||||||
|
->createQueryBuilder('gu')
|
||||||
|
;
|
||||||
|
return $qb
|
||||||
|
->select(sprintf('NEW %s(gu.id, gu.unitName, gu.unitRefId, IDENTITY(gu.layer))', GeographicalUnit\SimpleGeographicalUnitDTO::class))
|
||||||
|
->innerJoin(Address::class, 'address', Join::WITH, 'ST_CONTAINS(gu.geom, address.point) = TRUE')
|
||||||
|
->where($qb->expr()->eq('address', ':address'))
|
||||||
|
->setParameter('address', $address)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function find($id): ?GeographicalUnit
|
public function find($id): ?GeographicalUnit
|
||||||
|
@ -11,8 +11,23 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\MainBundle\Repository;
|
namespace Chill\MainBundle\Repository;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Chill\MainBundle\Entity\GeographicalUnit\SimpleGeographicalUnitDTO;
|
||||||
use Doctrine\Persistence\ObjectRepository;
|
use Doctrine\Persistence\ObjectRepository;
|
||||||
|
|
||||||
interface GeographicalUnitRepositoryInterface extends ObjectRepository
|
interface GeographicalUnitRepositoryInterface extends ObjectRepository
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Return the geographical units as @link{SimpleGeographicalUnitDTO} whithin the address is contained.
|
||||||
|
*
|
||||||
|
* This query is executed in real time (without the refresh of the materialized view which load the addresses).
|
||||||
|
*
|
||||||
|
* @param Address $address
|
||||||
|
* @param int $offset
|
||||||
|
* @param int $limit
|
||||||
|
* @return SimpleGeographicalUnitDTO[]
|
||||||
|
*/
|
||||||
|
public function findGeographicalUnitContainingAddress(Address $address, int $offset = 0, int $limit = 50): array;
|
||||||
|
|
||||||
|
public function countGeographicalUnitContainingAddress(Address $address): int;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
import {Address, GeographicalUnitLayer, SimpleGeographicalUnit} from "../../types";
|
||||||
|
import {fetchResults, makeFetch} from "./apiMethods";
|
||||||
|
|
||||||
|
export const getAddressById = async (address_id: number): Promise<Address> =>
|
||||||
|
{
|
||||||
|
const url = `/api/1.0/main/address/${address_id}.json`;
|
||||||
|
|
||||||
|
const response = await fetch(url);
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw Error('Error with request resource response');
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getGeographicalUnitsByAddress = async (address: Address): Promise<SimpleGeographicalUnit[]> => {
|
||||||
|
return fetchResults<SimpleGeographicalUnit>(`/api/1.0/main/geographical-unit/by-address/${address.address_id}.json`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getAllGeographicalUnitLayers = async (): Promise<GeographicalUnitLayer[]> => {
|
||||||
|
return fetchResults<GeographicalUnitLayer>(`/api/1.0/main/geographical-unit-layer.json`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const syncAddressWithReference = async (address: Address): Promise<Address> => {
|
||||||
|
return makeFetch<null, Address>("POST", `/api/1.0/main/address/reference-match/${address.address_id}/sync-with-reference`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const markAddressReviewed = async (address: Address): Promise<Address> => {
|
||||||
|
return makeFetch<null, Address>("POST", `/api/1.0/main/address/reference-match/${address.address_id}/set/reviewed`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const markAddressToReview = async (address: Address): Promise<Address> => {
|
||||||
|
return makeFetch<null, Address>("POST", `/api/1.0/main/address/reference-match/${address.address_id}/set/to_review`);
|
||||||
|
}
|
@ -67,9 +67,6 @@ export const makeFetch = <Input, Output>(method: 'POST'|'GET'|'PUT'|'PATCH'|'DEL
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('for url '+url, body);
|
|
||||||
console.log('for url '+url, body !== null);
|
|
||||||
|
|
||||||
if (body !== null && typeof body !== 'undefined') {
|
if (body !== null && typeof body !== 'undefined') {
|
||||||
Object.assign(opts, {body: JSON.stringify(body)})
|
Object.assign(opts, {body: JSON.stringify(body)})
|
||||||
}
|
}
|
||||||
@ -77,9 +74,6 @@ export const makeFetch = <Input, Output>(method: 'POST'|'GET'|'PUT'|'PATCH'|'DEL
|
|||||||
if (typeof options !== 'undefined') {
|
if (typeof options !== 'undefined') {
|
||||||
opts = Object.assign(opts, options);
|
opts = Object.assign(opts, options);
|
||||||
}
|
}
|
||||||
console.log('will fetch', url);
|
|
||||||
console.log('content for ' + url, opts);
|
|
||||||
|
|
||||||
return fetch(url, opts)
|
return fetch(url, opts)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
import AddressDetailsButton from "../../vuejs/_components/AddressDetails/AddressDetailsButton.vue";
|
||||||
|
import {createApp} from "vue";
|
||||||
|
import {createI18n} from "vue-i18n";
|
||||||
|
import {_createI18n} from "../../vuejs/_js/i18n";
|
||||||
|
import {Address} from "../../types";
|
||||||
|
|
||||||
|
const i18n = _createI18n({});
|
||||||
|
|
||||||
|
document.querySelectorAll<HTMLSpanElement>('span[data-address-details]').forEach((el) => {
|
||||||
|
const dataset = el.dataset as {
|
||||||
|
addressId: string,
|
||||||
|
addressRefStatus: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
const app = createApp({
|
||||||
|
components: {AddressDetailsButton},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
addressId: Number.parseInt(dataset.addressId),
|
||||||
|
addressRefStatus: dataset.addressRefStatus,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: '<address-details-button :address_id="addressId" :address_ref_status="addressRefStatus" @update-address="onUpdateAddress"></address-details-button>',
|
||||||
|
methods: {
|
||||||
|
onUpdateAddress: (address: Address): void => {
|
||||||
|
if (address.refStatus === 'to_review' || address.refStatus === 'reviewed') {
|
||||||
|
// in this two case, the address content do not change
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (window.confirm("L'adresse a été modifiée. Vous pouvez continuer votre travail. Cependant, pour afficher les données immédiatement, veuillez recharger la page. \n\n Voulez-vous recharger la page immédiatement ?")) {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.use(i18n);
|
||||||
|
app.mount(el);
|
||||||
|
});
|
@ -18,6 +18,7 @@ function loadDynamicPicker(element) {
|
|||||||
isMultiple = parseInt(el.dataset.multiple) === 1,
|
isMultiple = parseInt(el.dataset.multiple) === 1,
|
||||||
uniqId = el.dataset.uniqid,
|
uniqId = el.dataset.uniqid,
|
||||||
input = element.querySelector('[data-input-uniqid="'+ el.dataset.uniqid +'"]'),
|
input = element.querySelector('[data-input-uniqid="'+ el.dataset.uniqid +'"]'),
|
||||||
|
// the "picked" will always be an array, even if multiple is false
|
||||||
picked = isMultiple ?
|
picked = isMultiple ?
|
||||||
JSON.parse(input.value) : (
|
JSON.parse(input.value) : (
|
||||||
(input.value === '[]' || input.value === '') ?
|
(input.value === '[]' || input.value === '') ?
|
||||||
@ -54,16 +55,12 @@ function loadDynamicPicker(element) {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
notPickedSuggested() {
|
notPickedSuggested() {
|
||||||
if (this.multiple) {
|
|
||||||
const pickedIds = new Set();
|
const pickedIds = new Set();
|
||||||
for (const p of this.picked) {
|
for (const p of this.picked) {
|
||||||
pickedIds.add(`${p.type}${p.id}`);
|
pickedIds.add(`${p.type}${p.id}`);
|
||||||
}
|
}
|
||||||
return this.suggested.filter(e => !pickedIds.has(`${e.type}${e.id}`))
|
return this.suggested.filter(e => !pickedIds.has(`${e.type}${e.id}`))
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.suggested.filter(e => e.type !== this.picked.type && e.id !== e.picked.id);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addNewEntity({entity}) {
|
addNewEntity({entity}) {
|
||||||
@ -90,7 +87,11 @@ function loadDynamicPicker(element) {
|
|||||||
this.suggested.push(entity);
|
this.suggested.push(entity);
|
||||||
}
|
}
|
||||||
this.picked = this.picked.filter(e => !(e.type === entity.type && e.id === entity.id));
|
this.picked = this.picked.filter(e => !(e.type === entity.type && e.id === entity.id));
|
||||||
|
if (this.multiple) {
|
||||||
input.value = JSON.stringify(this.picked);
|
input.value = JSON.stringify(this.picked);
|
||||||
|
} else {
|
||||||
|
input.value = "";
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -70,6 +70,8 @@ export interface Country {
|
|||||||
code: string;
|
code: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AddressRefStatus = 'match'|'to_review'|'reviewed';
|
||||||
|
|
||||||
export interface Address {
|
export interface Address {
|
||||||
type: "address";
|
type: "address";
|
||||||
address_id: number;
|
address_id: number;
|
||||||
@ -90,6 +92,13 @@ export interface Address {
|
|||||||
addressReference: AddressReference | null;
|
addressReference: AddressReference | null;
|
||||||
validFrom: DateTime;
|
validFrom: DateTime;
|
||||||
validTo: DateTime | null;
|
validTo: DateTime | null;
|
||||||
|
point: Point | null;
|
||||||
|
refStatus: AddressRefStatus;
|
||||||
|
isNoAddress: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AddressWithPoint extends Address {
|
||||||
|
point: Point
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AddressReference {
|
export interface AddressReference {
|
||||||
@ -106,6 +115,19 @@ export interface AddressReference {
|
|||||||
updatedAt: DateTime | null;
|
updatedAt: DateTime | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SimpleGeographicalUnit {
|
||||||
|
id: number;
|
||||||
|
layerId: number;
|
||||||
|
unitName: string;
|
||||||
|
unitRefId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GeographicalUnitLayer {
|
||||||
|
id: number;
|
||||||
|
name: TranslatableString;
|
||||||
|
refId: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface Location {
|
export interface Location {
|
||||||
type: "location";
|
type: "location";
|
||||||
id: number;
|
id: number;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import {getAddressById} from 'ChillMainAssets/lib/api/address';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Endpoint chill_api_single_country__index
|
* Endpoint chill_api_single_country__index
|
||||||
* method GET, get Country Object
|
* method GET, get Country Object
|
||||||
@ -188,13 +190,7 @@ const postPostalCode = (postalCode) => { //<--
|
|||||||
* @returns {Promise} a promise containing a Address object
|
* @returns {Promise} a promise containing a Address object
|
||||||
*/
|
*/
|
||||||
const getAddress = (id) => {
|
const getAddress = (id) => {
|
||||||
//console.log('<< get address');
|
return getAddressById(id);
|
||||||
const url = `/api/1.0/main/address/${id}.json`;
|
|
||||||
return fetch(url)
|
|
||||||
.then(response => {
|
|
||||||
if (response.ok) { return response.json(); }
|
|
||||||
throw Error('Error with request resource response');
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
@ -580,15 +580,15 @@ export default {
|
|||||||
this.entity.selected.city = this.context.edit ? this.entity.address.postcode : {};
|
this.entity.selected.city = this.context.edit ? this.entity.address.postcode : {};
|
||||||
|
|
||||||
this.entity.selected.address = {};
|
this.entity.selected.address = {};
|
||||||
this.entity.selected.address.street = this.context.edit ? this.entity.address.street: null;
|
this.entity.selected.address.street = this.context.edit ? this.entity.address.street: '';
|
||||||
this.entity.selected.address.streetNumber = this.context.edit ? this.entity.address.streetNumber: null;
|
this.entity.selected.address.streetNumber = this.context.edit ? this.entity.address.streetNumber: '';
|
||||||
this.entity.selected.address.floor = this.context.edit ? this.entity.address.floor: null;
|
this.entity.selected.address.floor = this.context.edit ? this.entity.address.floor: '';
|
||||||
this.entity.selected.address.corridor = this.context.edit ? this.entity.address.corridor: null;
|
this.entity.selected.address.corridor = this.context.edit ? this.entity.address.corridor: '';
|
||||||
this.entity.selected.address.steps = this.context.edit ? this.entity.address.steps: null;
|
this.entity.selected.address.steps = this.context.edit ? this.entity.address.steps: '';
|
||||||
this.entity.selected.address.flat = this.context.edit ? this.entity.address.flat: null;
|
this.entity.selected.address.flat = this.context.edit ? this.entity.address.flat: '';
|
||||||
this.entity.selected.address.buildingName = this.context.edit ? this.entity.address.buildingName: null;
|
this.entity.selected.address.buildingName = this.context.edit ? this.entity.address.buildingName: '';
|
||||||
this.entity.selected.address.distribution = this.context.edit ? this.entity.address.distribution: null;
|
this.entity.selected.address.distribution = this.context.edit ? this.entity.address.distribution: '';
|
||||||
this.entity.selected.address.extra = this.context.edit ? this.entity.address.extra: null;
|
this.entity.selected.address.extra = this.context.edit ? this.entity.address.extra: '';
|
||||||
|
|
||||||
this.entity.selected.writeNew.address = this.context.edit && this.entity.address.addressReference === null && this.entity.address.street.length > 0
|
this.entity.selected.writeNew.address = this.context.edit && this.entity.address.addressReference === null && this.entity.address.street.length > 0
|
||||||
this.entity.selected.writeNew.postcode = false // NB: this used to be this.context.edit, but think it was erroneous;
|
this.entity.selected.writeNew.postcode = false // NB: this used to be this.context.edit, but think it was erroneous;
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
<template>
|
||||||
|
<span v-if="data.working_ref_status === 'to_review'" class="badge bg-danger address-details-button-warning">L'adresse de référence a été modifiée</span>
|
||||||
|
<a v-if="data.loading === false" @click.prevent="clickOrOpen" class="btn btn-sm btn-misc">
|
||||||
|
<span class="fa fa-map address-details-button"></span>
|
||||||
|
</a>
|
||||||
|
<span v-if="data.loading" class="fa fa-spin fa-spinner "></span>
|
||||||
|
<AddressModal :address="data.working_address" @update-address="onUpdateAddress" ref="address_modal"></AddressModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {Address, AddressRefStatus} from "../../../types";
|
||||||
|
import {onMounted, reactive, ref} from "vue";
|
||||||
|
import {getAddressById} from "../../../lib/api/address";
|
||||||
|
import AddressModal from "./AddressModal.vue";
|
||||||
|
|
||||||
|
export interface AddressModalContentProps {
|
||||||
|
address_id: number;
|
||||||
|
address_ref_status: AddressRefStatus | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = reactive<{
|
||||||
|
loading: boolean,
|
||||||
|
working_address: Address | null,
|
||||||
|
working_ref_status: AddressRefStatus | null,
|
||||||
|
}>({
|
||||||
|
loading: false,
|
||||||
|
working_address: null,
|
||||||
|
working_ref_status: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<AddressModalContentProps>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update-address', value: Address): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const address_modal = ref<InstanceType<typeof AddressModal> | null>(null);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
data.working_ref_status = props.address_ref_status;
|
||||||
|
});
|
||||||
|
|
||||||
|
async function clickOrOpen(): Promise<void> {
|
||||||
|
if (data.working_address === null) {
|
||||||
|
data.loading = true;
|
||||||
|
data.working_address = await getAddressById(props.address_id);
|
||||||
|
data.working_ref_status = data.working_address.refStatus;
|
||||||
|
data.loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open the modal
|
||||||
|
address_modal.value?.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
const onUpdateAddress = (address: Address): void => {
|
||||||
|
data.working_address = address;
|
||||||
|
data.working_ref_status = address.refStatus;
|
||||||
|
emit('update-address', address);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.address-details-button-warning {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 0.3rem;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,33 @@
|
|||||||
|
<template>
|
||||||
|
<address-render-box :address="props.address" :show-button-details="false"></address-render-box>
|
||||||
|
<address-details-ref-matching :address="props.address" @update-address="onUpdateAddress"></address-details-ref-matching>
|
||||||
|
<address-details-map :address="props.address"></address-details-map>
|
||||||
|
<address-details-geographical-layers :address="props.address"></address-details-geographical-layers>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {Address} from "../../../types";
|
||||||
|
import AddressDetailsMap from "./Parts/AddressDetailsMap.vue";
|
||||||
|
import AddressRenderBox from "../Entity/AddressRenderBox.vue";
|
||||||
|
import AddressDetailsGeographicalLayers from "./Parts/AddressDetailsGeographicalLayers.vue";
|
||||||
|
import AddressDetailsRefMatching from "./Parts/AddressDetailsRefMatching.vue";
|
||||||
|
|
||||||
|
interface AddressModalContentProps {
|
||||||
|
address: Address,
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<AddressModalContentProps>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update-address', value: Address): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const onUpdateAddress = (address: Address): void => {
|
||||||
|
emit('update-address', address);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,57 @@
|
|||||||
|
<template>
|
||||||
|
<teleport to="body">
|
||||||
|
<modal v-if="state.show_modal" @close="close">
|
||||||
|
<template v-slot:header>
|
||||||
|
<h2>Détails d'une adresse</h2>
|
||||||
|
</template>
|
||||||
|
<template v-slot:body>
|
||||||
|
<address-details-content :address="props.address" @update-address="onUpdateAddress"></address-details-content>
|
||||||
|
</template>
|
||||||
|
</modal>
|
||||||
|
</teleport>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {reactive, ref} from "vue";
|
||||||
|
import Modal from 'ChillMainAssets/vuejs/_components/Modal.vue';
|
||||||
|
import {Address} from "../../../types";
|
||||||
|
import AddressDetailsContent from "./AddressDetailsContent.vue";
|
||||||
|
|
||||||
|
interface AddressModalProps {
|
||||||
|
address: Address
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AddressModalState {
|
||||||
|
show_modal: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<AddressModalProps>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update-address', value: Address): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const state: AddressModalState = reactive({show_modal: false});
|
||||||
|
|
||||||
|
const open = (): void => {
|
||||||
|
state.show_modal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const close = (): void => {
|
||||||
|
state.show_modal = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onUpdateAddress = (address: Address): void => {
|
||||||
|
emit('update-address', address);
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
close,
|
||||||
|
open,
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,55 @@
|
|||||||
|
<template>
|
||||||
|
<template v-for="container in data.containers">
|
||||||
|
<h4>{{ container.layer.name.fr }}</h4>
|
||||||
|
<ul>
|
||||||
|
<li v-for="unit in container.units">{{ unit.unitName }} ({{ unit.unitRefId }})</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
import {Address, GeographicalUnitLayer, SimpleGeographicalUnit} from "../../../../types";
|
||||||
|
import {getGeographicalUnitsByAddress, getAllGeographicalUnitLayers} from "../../../../lib/api/address";
|
||||||
|
import {onMounted, reactive} from "vue";
|
||||||
|
|
||||||
|
export interface AddressDetailsGeographicalLayersProp {
|
||||||
|
address: Address
|
||||||
|
};
|
||||||
|
|
||||||
|
interface GeographicalUnitContainer {
|
||||||
|
layer: GeographicalUnitLayer;
|
||||||
|
units: SimpleGeographicalUnit[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<AddressDetailsGeographicalLayersProp>();
|
||||||
|
|
||||||
|
const data: {
|
||||||
|
containers: GeographicalUnitContainer[]
|
||||||
|
} = reactive({
|
||||||
|
containers: []
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const [units, layers] = await Promise.all([
|
||||||
|
getGeographicalUnitsByAddress(props.address),
|
||||||
|
getAllGeographicalUnitLayers()
|
||||||
|
]) as [SimpleGeographicalUnit[], GeographicalUnitLayer[]];
|
||||||
|
|
||||||
|
for (let layer of layers) {
|
||||||
|
let us = units.filter((u) => u.layerId === layer.id);
|
||||||
|
if (us.length > 0) {
|
||||||
|
data.containers.push({
|
||||||
|
layer,
|
||||||
|
units: us
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -0,0 +1,90 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="props.address.isNoAddress" class="alert alert-info">
|
||||||
|
Cette adresse est incomplète. La position géographique est approximative.
|
||||||
|
</div>
|
||||||
|
<div v-if="props.address.point !== null" class="address_details_map" ref="map_div"></div>
|
||||||
|
<p>Voir sur <a :href="makeUrlGoogleMap(props.address)" target="_blank">Google Maps</a> <a :href="makeUrlOsm(props.address)" target="_blank">OSM</a></p>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import {onMounted, ref} from "vue";
|
||||||
|
import 'leaflet/dist/leaflet.css';
|
||||||
|
import markerIconPng from "leaflet/dist/images/marker-icon.png";
|
||||||
|
import L, {LatLngExpression, LatLngTuple} from "leaflet";
|
||||||
|
import {Address, Point} from "../../../../types";
|
||||||
|
|
||||||
|
const lonLatForLeaflet = (point: Point): LatLngTuple => {
|
||||||
|
return [point.coordinates[1], point.coordinates[0]];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MapProps {
|
||||||
|
address: Address,
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<MapProps>();
|
||||||
|
|
||||||
|
const map_div = ref<HTMLDivElement | null>(null)
|
||||||
|
let map: L.Map|null = null;
|
||||||
|
let marker: L.Marker|null = null;
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (map_div.value === null) {
|
||||||
|
// there is no map div when the address does not have any Point
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (props.address.point !== null) {
|
||||||
|
map = L.map(map_div.value);
|
||||||
|
map.setView(lonLatForLeaflet(props.address.point), 18);
|
||||||
|
|
||||||
|
|
||||||
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||||
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
|
||||||
|
const markerIcon = L.icon({
|
||||||
|
iconUrl: markerIconPng,
|
||||||
|
iconAnchor: [12, 41],
|
||||||
|
});
|
||||||
|
|
||||||
|
marker = L.marker(lonLatForLeaflet(props.address.point), {icon: markerIcon});
|
||||||
|
marker.addTo(map);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const makeUrlGoogleMap = (address: Address): string => {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.append('api', '1');
|
||||||
|
if (address.point !== null && address.addressReference !== null) {
|
||||||
|
params.append('query', `${address.point.coordinates[1]} ${address.point.coordinates[0]}`);
|
||||||
|
} else {
|
||||||
|
params.append('query', address.lines.join(', '));
|
||||||
|
}
|
||||||
|
|
||||||
|
return `https://www.google.com/maps/search/?${params.toString()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const makeUrlOsm = (address: Address): string => {
|
||||||
|
if (address.point !== null && address.addressReference !== null) {
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.append('mlat', `${address.point.coordinates[1]}`);
|
||||||
|
params.append('mlon', `${address.point.coordinates[0]}`);
|
||||||
|
const hashParams = new URLSearchParams();
|
||||||
|
hashParams.append('map', `18/${address.point.coordinates[1]}/${address.point.coordinates[0]}`);
|
||||||
|
|
||||||
|
return `https://www.openstreetmap.org/?${params.toString()}#${hashParams.toString()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.append('query', address.lines.join(', '));
|
||||||
|
|
||||||
|
return `https://www.openstreetmap.org/search?${params.toString()}`;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
div.address_details_map {
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,96 @@
|
|||||||
|
<template>
|
||||||
|
<template v-if="props.address.refStatus !== 'match'">
|
||||||
|
<div v-if="props.address.refStatus === 'to_review' || props.address.refStatus === 'reviewed'" :class="{alert: true, 'alert-danger': props.address.refStatus === 'to_review', 'alert-warning': props.address.refStatus === 'reviewed'}">
|
||||||
|
<p v-if="props.address.refStatus === 'to_review'"><i class="fa fa-warning"></i> L'adresse de référence a été modifiée.</p>
|
||||||
|
<p v-if="props.address.refStatus === 'reviewed'">L'adresse est conservée, mais diffère de l'adresse de référence.</p>
|
||||||
|
|
||||||
|
<template v-if="props.address.addressReference.street !== props.address.street || props.address.addressReference.streetNumber !== props.address.streetNumber">
|
||||||
|
<template v-if="props.address.country.code === 'BE'">
|
||||||
|
<div class="difference">
|
||||||
|
<span class="old">{{ props.address.street }} {{props.address.streetNumber}}</span>
|
||||||
|
<span class="new">{{ props.address.addressReference.street }} {{ props.address.addressReference.streetNumber }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div class="difference">
|
||||||
|
<span class="old">{{props.address.streetNumber}} {{ props.address.street }}</span>
|
||||||
|
<span class="new">{{ props.address.addressReference.streetNumber }} {{ props.address.addressReference.street }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-if="props.address.addressReference.postcode.id !== props.address.postcode.id">
|
||||||
|
<div class="difference">
|
||||||
|
<span class="old">{{ props.address.postcode.code }} {{props.address.postcode.name }}</span>
|
||||||
|
<span class="new">{{ props.address.addressReference.postcode.code }} {{ props.address.addressReference.postcode.name }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-if="props.address.point !== null && (props.address.point.coordinates[0] !== props.address.addressReference.point.coordinates[0] || props.address.point.coordinates[1] !== props.address.addressReference.point.coordinates[1])">
|
||||||
|
<div class="difference">
|
||||||
|
<span class="old">{{ props.address.point.coordinates[0] }} {{ props.address.point.coordinates[1]}}</span>
|
||||||
|
<span class="new">{{ props.address.addressReference.point.coordinates[0] }} {{ props.address.addressReference.point.coordinates[1]}}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<ul class="record_actions">
|
||||||
|
<li v-if="props.address.refStatus === 'to_review'"><button class="btn btn-sm btn-update" @click="applyUpdate">Appliquer les modifications</button></li>
|
||||||
|
<li v-if="props.address.refStatus === 'to_review'"><button class="btn btn-sm btn-primary" @click="keepCurrentAddress">Conserver</button></li>
|
||||||
|
<li v-if="props.address.refStatus === 'reviewed'"><button class="btn btn-sm btn-primary" @click="backToReview">Ré-examiner</button></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
|
||||||
|
import {Address} from "../../../../types";
|
||||||
|
import {markAddressReviewed, markAddressToReview, syncAddressWithReference} from "../../../../lib/api/address";
|
||||||
|
|
||||||
|
export interface AddressDetailsRefMatchingProps {
|
||||||
|
address: Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<AddressDetailsRefMatchingProps>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'update-address', value: Address): void
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const applyUpdate = async () => {
|
||||||
|
const new_address = await syncAddressWithReference(props.address);
|
||||||
|
|
||||||
|
emit('update-address', new_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
const keepCurrentAddress = async () => {
|
||||||
|
const new_address = await markAddressReviewed(props.address);
|
||||||
|
|
||||||
|
emit("update-address", new_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
const backToReview = async () => {
|
||||||
|
const new_address = await markAddressToReview(props.address);
|
||||||
|
|
||||||
|
emit("update-address", new_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.difference {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.old {
|
||||||
|
text-decoration: red line-through;
|
||||||
|
}
|
||||||
|
.new {
|
||||||
|
font-weight: bold;
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -11,17 +11,18 @@
|
|||||||
<p v-for="(l, i) in address.lines" :key="`line-${i}`">
|
<p v-for="(l, i) in address.lines" :key="`line-${i}`">
|
||||||
{{ l }}
|
{{ l }}
|
||||||
</p>
|
</p>
|
||||||
|
<p v-if="showButtonDetails"><address-details-button :address_id="address.address_id" :address_ref_status="address.refStatus"></address-details-button></p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<p v-if="address.text"
|
<p v-if="'' !== address.text"
|
||||||
class="street">
|
class="street">
|
||||||
{{ address.text }}
|
{{ address.text }}
|
||||||
</p>
|
</p>
|
||||||
<p v-if="address.postcode"
|
<p v-if="null !== address.postcode"
|
||||||
class="postcode">
|
class="postcode">
|
||||||
{{ address.postcode.code }} {{ address.postcode.name }}
|
{{ address.postcode.code }} {{ address.postcode.name }}
|
||||||
</p>
|
</p>
|
||||||
<p v-if="address.country"
|
<p v-if="null !== address.country"
|
||||||
class="country">
|
class="country">
|
||||||
{{ address.country.name.fr }}
|
{{ address.country.name.fr }}
|
||||||
</p>
|
</p>
|
||||||
@ -35,11 +36,12 @@
|
|||||||
<p v-for="(l, i) in address.lines" :key="`line-${i}`">
|
<p v-for="(l, i) in address.lines" :key="`line-${i}`">
|
||||||
{{ l }}
|
{{ l }}
|
||||||
</p>
|
</p>
|
||||||
|
<p v-if="showButtonDetails"><address-details-button :address_id="address.address_id" :address_ref_status="address.refStatus"></address-details-button></p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<p v-if="address.text"
|
<p v-if="address.text"
|
||||||
class="street">
|
class="street">
|
||||||
{{ address.text }}
|
{{ address.text }} <template v-if="showButtonDetails"><address-details-button :address_id="address.address_id" :address_ref_status="address.refStatus"></address-details-button></template>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -65,11 +67,13 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
import Confidential from 'ChillMainAssets/vuejs/_components/Confidential.vue';
|
import Confidential from 'ChillMainAssets/vuejs/_components/Confidential.vue';
|
||||||
|
import AddressDetailsButton from "ChillMainAssets/vuejs/_components/AddressDetails/AddressDetailsButton.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AddressRenderBox',
|
name: 'AddressRenderBox',
|
||||||
components: {
|
components: {
|
||||||
Confidential
|
Confidential,
|
||||||
|
AddressDetailsButton,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
address: {
|
address: {
|
||||||
@ -82,6 +86,10 @@ export default {
|
|||||||
useDatePane: {
|
useDatePane: {
|
||||||
default: false,
|
default: false,
|
||||||
type: Boolean
|
type: Boolean
|
||||||
|
},
|
||||||
|
showButtonDetails: {
|
||||||
|
default: true,
|
||||||
|
type: Boolean
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -69,6 +69,7 @@
|
|||||||
<i class="fa fa-li fa-map-marker"></i>
|
<i class="fa fa-li fa-map-marker"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ _self.inline(address, options, streetLine, lines) }}
|
{{ _self.inline(address, options, streetLine, lines) }}
|
||||||
|
<span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}" ></span>
|
||||||
</li>
|
</li>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|
||||||
@ -78,6 +79,7 @@
|
|||||||
<i class="fa fa-fw fa-map-marker"></i>
|
<i class="fa fa-fw fa-map-marker"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ _self.inline(address, options, streetLine, lines) }}
|
{{ _self.inline(address, options, streetLine, lines) }}
|
||||||
|
<span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}"></span>
|
||||||
</span>
|
</span>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|
||||||
@ -102,6 +104,7 @@
|
|||||||
<div class="noaddress">
|
<div class="noaddress">
|
||||||
{{ 'address.consider homeless'|trans }}
|
{{ 'address.consider homeless'|trans }}
|
||||||
</div>
|
</div>
|
||||||
|
<p><span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}" ></span></p>
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="address{% if options['multiline'] %} multiline{% endif %}{% if options['with_delimiter'] %} delimiter{% endif %}">
|
<div class="address{% if options['multiline'] %} multiline{% endif %}{% if options['with_delimiter'] %} delimiter{% endif %}">
|
||||||
@ -109,6 +112,7 @@
|
|||||||
<i class="fa fa-fw fa-map-marker"></i>
|
<i class="fa fa-fw fa-map-marker"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ _self.raw(lines) }}
|
{{ _self.raw(lines) }}
|
||||||
|
<p><span data-address-details="1" data-address-id="{{ address.id|escape('html_attr') }}" data-address-ref-status="{{ address.refStatus|escape('html_attr') }}"></span></p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ _self.validity(address, options) }}
|
{{ _self.validity(address, options) }}
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
{{ form_row(transition_form.future_cc_users) }}
|
{{ form_row(transition_form.future_cc_users) }}
|
||||||
|
|
||||||
{{ form_row(transition_form.future_dest_emails) }}
|
{{ form_row(transition_form.future_dest_emails) }}
|
||||||
|
{{ form_errors(transition_form.future_dest_users) }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>{{ form_label(transition_form.comment) }}</p>
|
<p>{{ form_label(transition_form.comment) }}</p>
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
{{ encore_entry_link_tags('chill') }}
|
{{ encore_entry_link_tags('chill') }}
|
||||||
{{ encore_entry_link_tags('mod_blur') }}
|
{{ encore_entry_link_tags('mod_blur') }}
|
||||||
{{ encore_entry_link_tags('vue_onthefly') }}
|
{{ encore_entry_link_tags('vue_onthefly') }}
|
||||||
|
{{ encore_entry_link_tags('mod_address_details') }}
|
||||||
{% block css %}<!-- nothing added to css -->{% endblock %}
|
{% block css %}<!-- nothing added to css -->{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@ -112,6 +113,7 @@
|
|||||||
{{ encore_entry_script_tags('mod_blur') }}
|
{{ encore_entry_script_tags('mod_blur') }}
|
||||||
{{ encore_entry_script_tags('chill') }}
|
{{ encore_entry_script_tags('chill') }}
|
||||||
{{ encore_entry_script_tags('vue_onthefly') }}
|
{{ encore_entry_script_tags('vue_onthefly') }}
|
||||||
|
{{ encore_entry_script_tags('mod_address_details') }}
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
window.addEventListener('DOMContentLoaded', function(e) {
|
window.addEventListener('DOMContentLoaded', function(e) {
|
||||||
|
@ -11,8 +11,8 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\MainBundle\Search;
|
namespace Chill\MainBundle\Search;
|
||||||
|
|
||||||
use Chill\MainBundle\Pagination\Paginator;
|
|
||||||
use Chill\MainBundle\Pagination\PaginatorFactory;
|
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||||
|
use Chill\MainBundle\Pagination\PaginatorInterface;
|
||||||
use Chill\MainBundle\Serializer\Model\Collection;
|
use Chill\MainBundle\Serializer\Model\Collection;
|
||||||
use Doctrine\DBAL\Types\Types;
|
use Doctrine\DBAL\Types\Types;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
@ -30,7 +30,7 @@ class SearchApi
|
|||||||
|
|
||||||
private PaginatorFactory $paginator;
|
private PaginatorFactory $paginator;
|
||||||
|
|
||||||
private iterable $providers = [];
|
private iterable $providers;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
EntityManagerInterface $em,
|
EntityManagerInterface $em,
|
||||||
@ -42,9 +42,6 @@ class SearchApi
|
|||||||
$this->paginator = $paginator;
|
$this->paginator = $paginator;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Model/Result[]
|
|
||||||
*/
|
|
||||||
public function getResults(string $pattern, array $types, array $parameters): Collection
|
public function getResults(string $pattern, array $types, array $parameters): Collection
|
||||||
{
|
{
|
||||||
$queries = $this->findQueries($pattern, $types, $parameters);
|
$queries = $this->findQueries($pattern, $types, $parameters);
|
||||||
@ -53,10 +50,10 @@ class SearchApi
|
|||||||
throw new SearchApiNoQueryException($pattern, $types, $parameters);
|
throw new SearchApiNoQueryException($pattern, $types, $parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
$total = $this->countItems($queries, $types, $parameters);
|
$total = $this->countItems($queries);
|
||||||
$paginator = $this->paginator->create($total);
|
$paginator = $this->paginator->create($total);
|
||||||
|
|
||||||
$rawResults = $this->fetchRawResult($queries, $types, $parameters, $paginator);
|
$rawResults = $this->fetchRawResult($queries, $types, $paginator);
|
||||||
|
|
||||||
$this->prepareProviders($rawResults);
|
$this->prepareProviders($rawResults);
|
||||||
$results = $this->buildResults($rawResults);
|
$results = $this->buildResults($rawResults);
|
||||||
@ -64,7 +61,7 @@ class SearchApi
|
|||||||
return new Collection($results, $paginator);
|
return new Collection($results, $paginator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildCountQuery(array $queries, $types, $parameters)
|
private function buildCountQuery(array $queries): array
|
||||||
{
|
{
|
||||||
$query = 'SELECT SUM(c) AS count FROM ({union_unordered}) AS sq';
|
$query = 'SELECT SUM(c) AS count FROM ({union_unordered}) AS sq';
|
||||||
$unions = [];
|
$unions = [];
|
||||||
@ -88,7 +85,7 @@ class SearchApi
|
|||||||
$items = [];
|
$items = [];
|
||||||
|
|
||||||
foreach ($rawResults as $r) {
|
foreach ($rawResults as $r) {
|
||||||
foreach ($this->providers as $k => $p) {
|
foreach ($this->providers as $p) {
|
||||||
if ($p->supportsResult($r['key'], $r['metadata'])) {
|
if ($p->supportsResult($r['key'], $r['metadata'])) {
|
||||||
$items[] = (new SearchApiResult($r['pertinence']))
|
$items[] = (new SearchApiResult($r['pertinence']))
|
||||||
->setResult(
|
->setResult(
|
||||||
@ -103,7 +100,7 @@ class SearchApi
|
|||||||
return $items;
|
return $items;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildUnionQuery(array $queries, $types, $parameters, Paginator $paginator)
|
private function buildUnionQuery(array $queries, PaginatorInterface $paginator): array
|
||||||
{
|
{
|
||||||
$query = '{unions} ORDER BY pertinence DESC LIMIT ? OFFSET ?';
|
$query = '{unions} ORDER BY pertinence DESC LIMIT ? OFFSET ?';
|
||||||
$unions = [];
|
$unions = [];
|
||||||
@ -126,9 +123,9 @@ class SearchApi
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function countItems($providers, $types, $parameters): int
|
private function countItems($providers): int
|
||||||
{
|
{
|
||||||
[$countQuery, $parameters] = $this->buildCountQuery($providers, $types, $parameters);
|
[$countQuery, $parameters] = $this->buildCountQuery($providers);
|
||||||
$rsmCount = new ResultSetMappingBuilder($this->em);
|
$rsmCount = new ResultSetMappingBuilder($this->em);
|
||||||
$rsmCount->addScalarResult('count', 'count');
|
$rsmCount->addScalarResult('count', 'count');
|
||||||
$countNq = $this->em->createNativeQuery($countQuery, $rsmCount);
|
$countNq = $this->em->createNativeQuery($countQuery, $rsmCount);
|
||||||
@ -137,9 +134,9 @@ class SearchApi
|
|||||||
return (int) $countNq->getSingleScalarResult();
|
return (int) $countNq->getSingleScalarResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function fetchRawResult($queries, $types, $parameters, Paginator $paginator): array
|
private function fetchRawResult($queries, $types, PaginatorInterface $paginator): array
|
||||||
{
|
{
|
||||||
[$union, $parameters] = $this->buildUnionQuery($queries, $types, $parameters, $paginator);
|
[$union, $parameters] = $this->buildUnionQuery($queries, $paginator);
|
||||||
$rsm = new ResultSetMappingBuilder($this->em);
|
$rsm = new ResultSetMappingBuilder($this->em);
|
||||||
$rsm->addScalarResult('key', 'key', Types::STRING)
|
$rsm->addScalarResult('key', 'key', Types::STRING)
|
||||||
->addScalarResult('metadata', 'metadata', Types::JSON)
|
->addScalarResult('metadata', 'metadata', Types::JSON)
|
||||||
@ -172,7 +169,7 @@ class SearchApi
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function prepareProviders(array $rawResults)
|
private function prepareProviders(array $rawResults): void
|
||||||
{
|
{
|
||||||
$metadatas = [];
|
$metadatas = [];
|
||||||
$providers = [];
|
$providers = [];
|
||||||
|
@ -16,6 +16,18 @@ use function count;
|
|||||||
use function implode;
|
use function implode;
|
||||||
use function strtr;
|
use function strtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This create a query optimized for searching for the api response.
|
||||||
|
*
|
||||||
|
* When build, this class generate a SQL string and a list of a parameters which is suitable for running
|
||||||
|
* a native SQL query. This have usually the form of
|
||||||
|
*
|
||||||
|
* `SELECT '<key>' as key, <metadata> as metadata, <pertinence> as pertinence FROM <from clause> WHERE <where clause>`.
|
||||||
|
*
|
||||||
|
* The clause between `<>` are provided through the dedicated method in this class (@link{self::setSelectKey},
|
||||||
|
* @link{self::setFromClause}), etc.).
|
||||||
|
*
|
||||||
|
*/
|
||||||
class SearchApiQuery
|
class SearchApiQuery
|
||||||
{
|
{
|
||||||
private ?string $fromClause = null;
|
private ?string $fromClause = null;
|
||||||
|
@ -71,9 +71,9 @@ interface SearchInterface
|
|||||||
* @param array $terms the string to search
|
* @param array $terms the string to search
|
||||||
* @param int $start the first result (for pagination)
|
* @param int $start the first result (for pagination)
|
||||||
* @param int $limit the number of result (for pagination)
|
* @param int $limit the number of result (for pagination)
|
||||||
* @param string $format The format for result
|
* @param "html"|"json" $format The format for result
|
||||||
*
|
*
|
||||||
* @return string, an HTML string
|
* @return string|array a string if format is html, an array if format is json
|
||||||
*/
|
*/
|
||||||
public function renderResult(array $terms, $start = 0, $limit = 50, array $options = [], $format = 'html');
|
public function renderResult(array $terms, $start = 0, $limit = 50, array $options = [], $format = 'html');
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ use Chill\MainBundle\Entity\Scope;
|
|||||||
use Chill\MainBundle\Entity\User;
|
use Chill\MainBundle\Entity\User;
|
||||||
use Chill\MainBundle\Repository\UserACLAwareRepositoryInterface;
|
use Chill\MainBundle\Repository\UserACLAwareRepositoryInterface;
|
||||||
use Chill\MainBundle\Security\ParentRoleHelper;
|
use Chill\MainBundle\Security\ParentRoleHelper;
|
||||||
use Chill\MainBundle\Security\Resolver\CenterResolverDispatcherInterface;
|
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
|
||||||
use Chill\MainBundle\Security\Resolver\ScopeResolverDispatcher;
|
use Chill\MainBundle\Security\Resolver\ScopeResolverDispatcher;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Symfony\Component\Security\Core\Role\Role;
|
use Symfony\Component\Security\Core\Role\Role;
|
||||||
@ -34,7 +34,7 @@ use function get_class;
|
|||||||
*/
|
*/
|
||||||
class AuthorizationHelper implements AuthorizationHelperInterface
|
class AuthorizationHelper implements AuthorizationHelperInterface
|
||||||
{
|
{
|
||||||
private CenterResolverDispatcherInterface $centerResolverDispatcher;
|
private CenterResolverManagerInterface $centerResolverManager;
|
||||||
|
|
||||||
private LoggerInterface $logger;
|
private LoggerInterface $logger;
|
||||||
|
|
||||||
@ -45,13 +45,13 @@ class AuthorizationHelper implements AuthorizationHelperInterface
|
|||||||
private UserACLAwareRepositoryInterface $userACLAwareRepository;
|
private UserACLAwareRepositoryInterface $userACLAwareRepository;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
CenterResolverDispatcherInterface $centerResolverDispatcher,
|
CenterResolverManagerInterface $centerResolverManager,
|
||||||
LoggerInterface $logger,
|
LoggerInterface $logger,
|
||||||
ScopeResolverDispatcher $scopeResolverDispatcher,
|
ScopeResolverDispatcher $scopeResolverDispatcher,
|
||||||
UserACLAwareRepositoryInterface $userACLAwareRepository,
|
UserACLAwareRepositoryInterface $userACLAwareRepository,
|
||||||
ParentRoleHelper $parentRoleHelper
|
ParentRoleHelper $parentRoleHelper
|
||||||
) {
|
) {
|
||||||
$this->centerResolverDispatcher = $centerResolverDispatcher;
|
$this->centerResolverManager = $centerResolverManager;
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
$this->scopeResolverDispatcher = $scopeResolverDispatcher;
|
$this->scopeResolverDispatcher = $scopeResolverDispatcher;
|
||||||
$this->userACLAwareRepository = $userACLAwareRepository;
|
$this->userACLAwareRepository = $userACLAwareRepository;
|
||||||
@ -63,7 +63,7 @@ class AuthorizationHelper implements AuthorizationHelperInterface
|
|||||||
*
|
*
|
||||||
* @param User $user The user
|
* @param User $user The user
|
||||||
* @param array $centers a list of centers which are going to be filtered
|
* @param array $centers a list of centers which are going to be filtered
|
||||||
* @param Center|string $role
|
* @param mixed $role
|
||||||
*/
|
*/
|
||||||
public function filterReachableCenters(User $user, array $centers, $role): array
|
public function filterReachableCenters(User $user, array $centers, $role): array
|
||||||
{
|
{
|
||||||
@ -113,13 +113,14 @@ class AuthorizationHelper implements AuthorizationHelperInterface
|
|||||||
* Get reachable Centers for the given user, role,
|
* Get reachable Centers for the given user, role,
|
||||||
* and optionally Scope.
|
* and optionally Scope.
|
||||||
*
|
*
|
||||||
* @return array|Center[]
|
* @return list<Center>
|
||||||
*/
|
*/
|
||||||
public function getReachableCenters(UserInterface $user, string $role, ?Scope $scope = null): array
|
public function getReachableCenters(UserInterface $user, string $role, ?Scope $scope = null): array
|
||||||
{
|
{
|
||||||
if ($role instanceof Role) {
|
if ($role instanceof Role) {
|
||||||
$role = $role->getRole();
|
$role = $role->getRole();
|
||||||
}
|
}
|
||||||
|
/** @var array<string, Center> $centers */
|
||||||
$centers = [];
|
$centers = [];
|
||||||
|
|
||||||
foreach ($user->getGroupCenters() as $groupCenter) {
|
foreach ($user->getGroupCenters() as $groupCenter) {
|
||||||
@ -129,13 +130,13 @@ class AuthorizationHelper implements AuthorizationHelperInterface
|
|||||||
//check that the role is in the reachable roles
|
//check that the role is in the reachable roles
|
||||||
if ($this->isRoleReached($role, $roleScope->getRole())) {
|
if ($this->isRoleReached($role, $roleScope->getRole())) {
|
||||||
if (null === $scope) {
|
if (null === $scope) {
|
||||||
$centers[] = $groupCenter->getCenter();
|
$centers[spl_object_hash($groupCenter->getCenter())] = $groupCenter->getCenter();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($scope->getId() === $roleScope->getScope()->getId()) {
|
if ($scope->getId() === $roleScope->getScope()->getId()) {
|
||||||
$centers[] = $groupCenter->getCenter();
|
$centers[spl_object_hash($groupCenter->getCenter())] = $groupCenter->getCenter();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -143,7 +144,7 @@ class AuthorizationHelper implements AuthorizationHelperInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $centers;
|
return array_values($centers);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -194,12 +195,8 @@ class AuthorizationHelper implements AuthorizationHelperInterface
|
|||||||
*
|
*
|
||||||
* @return array|Scope[]
|
* @return array|Scope[]
|
||||||
*/
|
*/
|
||||||
public function getReachableScopes(UserInterface $user, string $role, $center): array
|
public function getReachableScopes(UserInterface $user, string $role, Center|array $center): array
|
||||||
{
|
{
|
||||||
if ($role instanceof Role) {
|
|
||||||
$role = $role->getRole();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->getReachableCircles($user, $role, $center);
|
return $this->getReachableCircles($user, $role, $center);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,10 +249,9 @@ class AuthorizationHelper implements AuthorizationHelperInterface
|
|||||||
*/
|
*/
|
||||||
public function userHasAccess(User $user, $entity, $attribute)
|
public function userHasAccess(User $user, $entity, $attribute)
|
||||||
{
|
{
|
||||||
$center = $this->centerResolverDispatcher->resolveCenter($entity);
|
$centers = $this->centerResolverManager->resolveCenters($entity);
|
||||||
|
|
||||||
if (is_iterable($center)) {
|
foreach ($centers as $c) {
|
||||||
foreach ($center as $c) {
|
|
||||||
if ($this->userHasAccessForCenter($user, $c, $entity, $attribute)) {
|
if ($this->userHasAccessForCenter($user, $c, $entity, $attribute)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -264,17 +260,6 @@ class AuthorizationHelper implements AuthorizationHelperInterface
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($center instanceof Center) {
|
|
||||||
return $this->userHasAccessForCenter($user, $center, $entity, $attribute);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null === $center) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new UnexpectedValueException('could not resolver a center');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if a parent role may give access to a given child role.
|
* Test if a parent role may give access to a given child role.
|
||||||
*
|
*
|
||||||
|
@ -21,12 +21,12 @@ interface AuthorizationHelperInterface
|
|||||||
* Get reachable Centers for the given user, role,
|
* Get reachable Centers for the given user, role,
|
||||||
* and optionnaly Scope.
|
* and optionnaly Scope.
|
||||||
*
|
*
|
||||||
* @return Center[]
|
* @return list<Center>
|
||||||
*/
|
*/
|
||||||
public function getReachableCenters(UserInterface $user, string $role, ?Scope $scope = null): array;
|
public function getReachableCenters(UserInterface $user, string $role, ?Scope $scope = null): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array|Center|Center[] $center
|
* @param Center|list<Center> $center
|
||||||
*/
|
*/
|
||||||
public function getReachableScopes(UserInterface $user, string $role, $center): array;
|
public function getReachableScopes(UserInterface $user, string $role, Center|array $center): array;
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,13 @@ class AddressNormalizer implements ContextAwareNormalizerInterface, NormalizerAw
|
|||||||
);
|
);
|
||||||
$data['validFrom'] = $address->getValidFrom();
|
$data['validFrom'] = $address->getValidFrom();
|
||||||
$data['validTo'] = $address->getValidTo();
|
$data['validTo'] = $address->getValidTo();
|
||||||
|
$data['refStatus'] = $address->getRefStatus();
|
||||||
|
$data['point'] = $this->normalizer->normalize(
|
||||||
|
$address->getPoint(),
|
||||||
|
$format,
|
||||||
|
[AbstractNormalizer::GROUPS => ['read']]
|
||||||
|
);
|
||||||
|
$data['isNoAddress'] = $address->isNoAddress();
|
||||||
} elseif ('docgen' === $format) {
|
} elseif ('docgen' === $format) {
|
||||||
$dateContext = array_merge($context, ['docgen:expects' => DateTimeInterface::class]);
|
$dateContext = array_merge($context, ['docgen:expects' => DateTimeInterface::class]);
|
||||||
$data['validFrom'] = $this->normalizer->normalize($address->getValidFrom(), $format, $dateContext);
|
$data['validFrom'] = $this->normalizer->normalize($address->getValidFrom(), $format, $dateContext);
|
||||||
|
@ -24,12 +24,18 @@ class AddressReferenceBEFromBestAddress
|
|||||||
|
|
||||||
private AddressReferenceBaseImporter $baseImporter;
|
private AddressReferenceBaseImporter $baseImporter;
|
||||||
|
|
||||||
|
private AddressToReferenceMatcher $addressToReferenceMatcher;
|
||||||
|
|
||||||
private HttpClientInterface $client;
|
private HttpClientInterface $client;
|
||||||
|
|
||||||
public function __construct(HttpClientInterface $client, AddressReferenceBaseImporter $baseImporter)
|
public function __construct(
|
||||||
{
|
HttpClientInterface $client,
|
||||||
|
AddressReferenceBaseImporter $baseImporter,
|
||||||
|
AddressToReferenceMatcher $addressToReferenceMatcher
|
||||||
|
) {
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
$this->baseImporter = $baseImporter;
|
$this->baseImporter = $baseImporter;
|
||||||
|
$this->addressToReferenceMatcher = $addressToReferenceMatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function import(string $lang, array $lists): void
|
public function import(string $lang, array $lists): void
|
||||||
@ -89,16 +95,18 @@ class AddressReferenceBEFromBestAddress
|
|||||||
$record['municipality_objectid'],
|
$record['municipality_objectid'],
|
||||||
$record['postal_info_objectid'],
|
$record['postal_info_objectid'],
|
||||||
$record['streetname'],
|
$record['streetname'],
|
||||||
$record['housenumber'] . $record['boxnumber'],
|
$record['housenumber'] .($record['boxnumber'] !== '' ? ' bte '. $record['boxnumber'] : ''),
|
||||||
'bestaddress.' . $list,
|
'bestaddress.' . $list,
|
||||||
(float) $record['X'],
|
|
||||||
(float) $record['Y'],
|
(float) $record['Y'],
|
||||||
|
(float) $record['X'],
|
||||||
3812
|
3812
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->baseImporter->finalize();
|
$this->baseImporter->finalize();
|
||||||
|
|
||||||
|
$this->addressToReferenceMatcher->checkAddressesMatchingReferences();
|
||||||
|
|
||||||
gzclose($uncompressedStream);
|
gzclose($uncompressedStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,15 @@ class AddressReferenceFromBano
|
|||||||
{
|
{
|
||||||
private AddressReferenceBaseImporter $baseImporter;
|
private AddressReferenceBaseImporter $baseImporter;
|
||||||
|
|
||||||
|
private AddressToReferenceMatcher $addressToReferenceMatcher;
|
||||||
|
|
||||||
private HttpClientInterface $client;
|
private HttpClientInterface $client;
|
||||||
|
|
||||||
public function __construct(HttpClientInterface $client, AddressReferenceBaseImporter $baseImporter)
|
public function __construct(HttpClientInterface $client, AddressReferenceBaseImporter $baseImporter, AddressToReferenceMatcher $addressToReferenceMatcher)
|
||||||
{
|
{
|
||||||
$this->client = $client;
|
$this->client = $client;
|
||||||
$this->baseImporter = $baseImporter;
|
$this->baseImporter = $baseImporter;
|
||||||
|
$this->addressToReferenceMatcher = $addressToReferenceMatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function import(string $departementNo): void
|
public function import(string $departementNo): void
|
||||||
@ -82,6 +85,8 @@ class AddressReferenceFromBano
|
|||||||
|
|
||||||
$this->baseImporter->finalize();
|
$this->baseImporter->finalize();
|
||||||
|
|
||||||
|
$this->addressToReferenceMatcher->checkAddressesMatchingReferences();
|
||||||
|
|
||||||
fclose($file);
|
fclose($file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
<?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\MainBundle\Service\Import;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
|
use Doctrine\DBAL\Connection;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark existing addresses as to be reviewed regarding the
|
||||||
|
* address reference
|
||||||
|
*/
|
||||||
|
final class AddressToReferenceMatcher
|
||||||
|
{
|
||||||
|
private Connection $connection;
|
||||||
|
|
||||||
|
private LoggerInterface $logger;
|
||||||
|
|
||||||
|
private const LOG_PREFIX = '[address_to_reference_matcher] ';
|
||||||
|
|
||||||
|
private const SQL_MARK_TO_REVIEW_ADDRESS_UNMATCHING = <<<'SQL'
|
||||||
|
UPDATE chill_main_address a SET refstatus = '{{ to_review }}', refstatuslastupdate = NOW()
|
||||||
|
FROM chill_main_address_reference ar
|
||||||
|
WHERE
|
||||||
|
a.addressreference_id = ar.id
|
||||||
|
-- restrict only on active addresses
|
||||||
|
AND (a.validto IS NULL OR a.validto >= NOW())
|
||||||
|
-- only addresses that are marked matching or "to review", but before the update
|
||||||
|
AND
|
||||||
|
(a.refstatus LIKE '{{ matching }}'
|
||||||
|
OR (a.refstatus LIKE '{{ reviewed }}' AND a.refstatuslastupdate < ar.updatedat))
|
||||||
|
AND (
|
||||||
|
a.postcode_id != ar.postcode_id
|
||||||
|
OR a.street != ar.street
|
||||||
|
OR a.streetnumber != ar.streetnumber
|
||||||
|
OR ROUND(ST_X(a.point) * 1000000) <> ROUND(ST_X(ar.point) * 1000000)
|
||||||
|
OR ROUND(ST_Y(a.point) * 1000000) <> ROUND(ST_Y(ar.point) * 1000000)
|
||||||
|
)
|
||||||
|
SQL;
|
||||||
|
|
||||||
|
private const SQL_MARK_MATCHING_ADDRESSES_REVIEWED_OR_TO_REVIEW = <<<'SQL'
|
||||||
|
UPDATE chill_main_address a SET refstatus = '{{ matching }}', refstatuslastupdate = NOW()
|
||||||
|
FROM chill_main_address_reference ar
|
||||||
|
WHERE
|
||||||
|
a.addressreference_id = ar.id
|
||||||
|
-- restrict only on active addresses
|
||||||
|
AND (a.validto IS NULL OR a.validto >= NOW())
|
||||||
|
AND a.refstatus IN ('{{ to_review }}', '{{ reviewed }}')
|
||||||
|
AND a.postcode_id = ar.postcode_id
|
||||||
|
AND a.street = ar.street
|
||||||
|
AND a.streetnumber = ar.streetnumber
|
||||||
|
AND ROUND(ST_X(a.point) * 1000000) = ROUND(ST_X(ar.point) * 1000000)
|
||||||
|
AND ROUND(ST_Y(a.point) * 1000000) = ROUND(ST_Y(ar.point) * 1000000)
|
||||||
|
SQL;
|
||||||
|
|
||||||
|
private const SUBSTITUTES = [
|
||||||
|
'{{ to_review }}' => Address::ADDR_REFERENCE_STATUS_TO_REVIEW,
|
||||||
|
'{{ matching }}' => Address::ADDR_REFERENCE_STATUS_MATCH,
|
||||||
|
'{{ reviewed }}' => Address::ADDR_REFERENCE_STATUS_REVIEWED
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct(Connection $connection, LoggerInterface $logger)
|
||||||
|
{
|
||||||
|
$this->connection = $connection;
|
||||||
|
$this->logger = $logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkAddressesMatchingReferences(): void
|
||||||
|
{
|
||||||
|
$this->logger->notice(self::LOG_PREFIX.'Starting addresses matching');
|
||||||
|
|
||||||
|
$this->connection->transactional(function () {
|
||||||
|
$markedAsMatching = $this->connection->executeStatement(
|
||||||
|
strtr(self::SQL_MARK_MATCHING_ADDRESSES_REVIEWED_OR_TO_REVIEW, self::SUBSTITUTES)
|
||||||
|
);
|
||||||
|
|
||||||
|
$markedAsToReview = $this->connection->executeStatement(
|
||||||
|
strtr(self::SQL_MARK_TO_REVIEW_ADDRESS_UNMATCHING, self::SUBSTITUTES)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->logger->info(self::LOG_PREFIX.'Executed address matching', [
|
||||||
|
'marked_as_matching' => $markedAsMatching,
|
||||||
|
'marked_as_to_review' => $markedAsToReview,
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user