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 issue596_admin_user
This commit is contained in:
commit
b26fcc4566
16
CHANGELOG.md
16
CHANGELOG.md
@ -15,16 +15,24 @@ and this project adheres to
|
|||||||
* [admin] add admin section for languages and countries (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/596)
|
* [admin] add admin section for languages and countries (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/596)
|
||||||
* [activity] activity admin: translations + remove label field for comment on admin activity type (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/587)
|
* [activity] activity admin: translations + remove label field for comment on admin activity type (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/587)
|
||||||
* [main] admin user_job: improvements (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/588)
|
* [main] admin user_job: improvements (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/588)
|
||||||
|
* [address] can add extra address info even if noAddress (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/576)
|
||||||
|
|
||||||
|
|
||||||
|
## Test releases
|
||||||
|
|
||||||
|
### 2022-05-06
|
||||||
|
|
||||||
|
* [person] add civility when creating a person (with the on-the-fly component or in the php form) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/557)
|
||||||
|
* [person] add address when creating a person (with the on-the-fly component or in the php form) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/557)
|
||||||
|
* [person] add household creation API point (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/557)
|
||||||
|
|
||||||
|
### 2021-04-29
|
||||||
|
|
||||||
* [person] prevent circular references in PersonDocGenNormalizer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/527)
|
* [person] prevent circular references in PersonDocGenNormalizer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/527)
|
||||||
* [person] add maritalStatusComment to PersonDocGenNormalizer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/582)
|
* [person] add maritalStatusComment to PersonDocGenNormalizer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/582)
|
||||||
* Load relationships without gender in french fixtures
|
* Load relationships without gender in french fixtures
|
||||||
* Add command to remove old draft accompanying periods
|
* Add command to remove old draft accompanying periods
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Test releases
|
|
||||||
|
|
||||||
### 2021-04-28
|
### 2021-04-28
|
||||||
|
|
||||||
* [address] fix bug when editing address: update location and addressreferenceId + better update of the map in edition (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/593)
|
* [address] fix bug when editing address: update location and addressreferenceId + better update of the map in edition (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/593)
|
||||||
|
@ -85,8 +85,6 @@ class AccompanyingCourseDocumentVoter extends AbstractChillVoter implements Prov
|
|||||||
|
|
||||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
|
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
|
||||||
{
|
{
|
||||||
$this->logger->debug(sprintf('Voting from %s class', self::class));
|
|
||||||
|
|
||||||
if (!$token->getUser() instanceof User) {
|
if (!$token->getUser() instanceof User) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,8 @@ final class AddressReferenceAPIController extends ApiController
|
|||||||
protected function customizeQuery(string $action, Request $request, $qb): void
|
protected function customizeQuery(string $action, Request $request, $qb): void
|
||||||
{
|
{
|
||||||
if ($request->query->has('postal_code')) {
|
if ($request->query->has('postal_code')) {
|
||||||
$qb->where('e.postcode = :postal_code')
|
$qb->where($qb->expr()->isNull('e.deletedAt'))
|
||||||
|
->andWhere('e.postcode = :postal_code')
|
||||||
->setParameter('postal_code', $request->query->get('postal_code'));
|
->setParameter('postal_code', $request->query->get('postal_code'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,14 @@ 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 DateTimeImmutable;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use Symfony\Component\Serializer\Annotation\Groups;
|
use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Entity
|
* @ORM\Entity
|
||||||
* @ORM\Table(name="chill_main_address_reference", indexes={
|
* @ORM\Table(name="chill_main_address_reference", indexes={
|
||||||
* @ORM\Index(name="address_refid", columns={"refId"}, options={"where": "refid != ''"})
|
* @ORM\Index(name="address_refid", columns={"refId"})
|
||||||
* })
|
* })
|
||||||
* @ORM\HasLifecycleCallbacks
|
* @ORM\HasLifecycleCallbacks
|
||||||
*/
|
*/
|
||||||
@ -33,6 +34,18 @@ class AddressReference
|
|||||||
*/
|
*/
|
||||||
private string $addressCanonical = '';
|
private string $addressCanonical = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="datetime_immutable", nullable=true)
|
||||||
|
* @groups({"read"})
|
||||||
|
*/
|
||||||
|
private ?DateTimeImmutable $createdAt = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="datetime_immutable", nullable=true)
|
||||||
|
* @groups({"read"})
|
||||||
|
*/
|
||||||
|
private ?DateTimeImmutable $deletedAt = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Id
|
* @ORM\Id
|
||||||
* @ORM\GeneratedValue
|
* @ORM\GeneratedValue
|
||||||
@ -89,6 +102,22 @@ class AddressReference
|
|||||||
*/
|
*/
|
||||||
private $streetNumber;
|
private $streetNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="datetime_immutable", nullable=true)
|
||||||
|
* @groups({"read"})
|
||||||
|
*/
|
||||||
|
private ?DateTimeImmutable $updatedAt = null;
|
||||||
|
|
||||||
|
public function getCreatedAt(): ?DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDeletedAt(): ?DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->deletedAt;
|
||||||
|
}
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
{
|
{
|
||||||
return $this->id;
|
return $this->id;
|
||||||
@ -134,6 +163,25 @@ class AddressReference
|
|||||||
return $this->streetNumber;
|
return $this->streetNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getUpdatedAt(): ?DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCreatedAt(?DateTimeImmutable $createdAt): self
|
||||||
|
{
|
||||||
|
$this->createdAt = $createdAt;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDeletedAt(?DateTimeImmutable $deletedAt): self
|
||||||
|
{
|
||||||
|
$this->deletedAt = $deletedAt;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function setMunicipalityCode(?string $municipalityCode): self
|
public function setMunicipalityCode(?string $municipalityCode): self
|
||||||
{
|
{
|
||||||
$this->municipalityCode = $municipalityCode;
|
$this->municipalityCode = $municipalityCode;
|
||||||
@ -189,4 +237,11 @@ class AddressReference
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setUpdatedAt(?DateTimeImmutable $updatedAt): self
|
||||||
|
{
|
||||||
|
$this->updatedAt = $updatedAt;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,11 @@ use Symfony\Component\Serializer\Annotation\Groups;
|
|||||||
* @ORM\Entity
|
* @ORM\Entity
|
||||||
* @ORM\Table(
|
* @ORM\Table(
|
||||||
* name="chill_main_postal_code",
|
* name="chill_main_postal_code",
|
||||||
* indexes={@ORM\Index(
|
* indexes={
|
||||||
* name="search_name_code",
|
* @ORM\Index(name="search_name_code", columns={"code", "label"}),
|
||||||
* columns={"code", "label"}
|
* @ORM\Index(name="search_by_reference_code", columns={"code", "refpostalcodeid"})
|
||||||
* )})
|
* })
|
||||||
|
*
|
||||||
* @ORM\HasLifecycleCallbacks
|
* @ORM\HasLifecycleCallbacks
|
||||||
*/
|
*/
|
||||||
class PostalCode
|
class PostalCode
|
||||||
|
@ -45,7 +45,7 @@ class User implements AdvancedUserInterface
|
|||||||
*
|
*
|
||||||
* @ORM\Column(type="json", nullable=true)
|
* @ORM\Column(type="json", nullable=true)
|
||||||
*/
|
*/
|
||||||
private array $attributes;
|
private array $attributes = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\ManyToOne(targetEntity=Location::class)
|
* @ORM\ManyToOne(targetEntity=Location::class)
|
||||||
|
@ -130,12 +130,13 @@ final class AddressReferenceRepository implements ObjectRepository
|
|||||||
|
|
||||||
$query
|
$query
|
||||||
->setFromClause('chill_main_address_reference cma')
|
->setFromClause('chill_main_address_reference cma')
|
||||||
->andWhereClause('postcode_id = ?', [$postalCode->getId()]);
|
->andWhereClause('postcode_id = ?', [$postalCode->getId()])
|
||||||
|
->andWhereClause('deletedAt IS NULL', []);
|
||||||
|
|
||||||
$pertinenceClause = ['STRICT_WORD_SIMILARITY(addresscanonical, UNACCENT(?))'];
|
$pertinenceClause = ['STRICT_WORD_SIMILARITY(addresscanonical, UNACCENT(?))'];
|
||||||
$pertinenceArgs = [$pattern];
|
$pertinenceArgs = [$pattern];
|
||||||
$orWhere = ['addresscanonical %>> UNACCENT(?)'];
|
$andWhere = [];
|
||||||
$orWhereArgs = [$pattern];
|
$andWhereArgs = [];
|
||||||
|
|
||||||
foreach (explode(' ', $pattern) as $part) {
|
foreach (explode(' ', $pattern) as $part) {
|
||||||
$part = trim($part);
|
$part = trim($part);
|
||||||
@ -144,8 +145,8 @@ final class AddressReferenceRepository implements ObjectRepository
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$orWhere[] = "addresscanonical LIKE '%' || UNACCENT(LOWER(?)) || '%'";
|
$andWhere[] = "(addresscanonical LIKE '%' || UNACCENT(LOWER(?)) || '%')";
|
||||||
$orWhereArgs[] = $part;
|
$andWhereArgs[] = $part;
|
||||||
$pertinenceClause[] =
|
$pertinenceClause[] =
|
||||||
"(EXISTS (SELECT 1 FROM unnest(string_to_array(addresscanonical, ' ')) AS t WHERE starts_with(t, UNACCENT(LOWER(?)))))::int";
|
"(EXISTS (SELECT 1 FROM unnest(string_to_array(addresscanonical, ' ')) AS t WHERE starts_with(t, UNACCENT(LOWER(?)))))::int";
|
||||||
$pertinenceClause[] =
|
$pertinenceClause[] =
|
||||||
@ -154,7 +155,7 @@ final class AddressReferenceRepository implements ObjectRepository
|
|||||||
}
|
}
|
||||||
$query
|
$query
|
||||||
->setSelectPertinence(implode(' + ', $pertinenceClause), $pertinenceArgs)
|
->setSelectPertinence(implode(' + ', $pertinenceClause), $pertinenceArgs)
|
||||||
->andWhereClause(implode(' OR ', $orWhere), $orWhereArgs);
|
->andWhereClause(implode(' AND ', $andWhere), $andWhereArgs);
|
||||||
|
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
@ -51,9 +51,7 @@ function loadDynamicPicker(element) {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
addNewEntity(entity) {
|
addNewEntity(entity) {
|
||||||
console.log('addNewEntity', entity);
|
|
||||||
if (this.multiple) {
|
if (this.multiple) {
|
||||||
console.log('adding multiple');
|
|
||||||
if (!this.picked.some(el => {
|
if (!this.picked.some(el => {
|
||||||
return el.type === entity.type && el.id === entity.id;
|
return el.type === entity.type && el.id === entity.id;
|
||||||
})) {
|
})) {
|
||||||
@ -71,7 +69,6 @@ function loadDynamicPicker(element) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
removeEntity(entity) {
|
removeEntity(entity) {
|
||||||
console.log('removeEntity', 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));
|
||||||
input.value = JSON.stringify(this.picked);
|
input.value = JSON.stringify(this.picked);
|
||||||
},
|
},
|
||||||
@ -86,7 +83,6 @@ function loadDynamicPicker(element) {
|
|||||||
|
|
||||||
|
|
||||||
document.addEventListener('show-hide-show', function(e) {
|
document.addEventListener('show-hide-show', function(e) {
|
||||||
console.log('creation event caught')
|
|
||||||
loadDynamicPicker(e.detail.container)
|
loadDynamicPicker(e.detail.container)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -94,17 +90,14 @@ document.addEventListener('show-hide-hide', function(e) {
|
|||||||
console.log('hiding event caught')
|
console.log('hiding event caught')
|
||||||
e.detail.container.querySelectorAll('[data-module="pick-dynamic"]').forEach((el) => {
|
e.detail.container.querySelectorAll('[data-module="pick-dynamic"]').forEach((el) => {
|
||||||
let uniqId = el.dataset.uniqid;
|
let uniqId = el.dataset.uniqid;
|
||||||
console.log(uniqId);
|
|
||||||
if (appsOnPage.has(uniqId)) {
|
if (appsOnPage.has(uniqId)) {
|
||||||
appsOnPage.get(uniqId).unmount();
|
appsOnPage.get(uniqId).unmount();
|
||||||
console.log('App has been unmounted')
|
|
||||||
appsOnPage.delete(uniqId);
|
appsOnPage.delete(uniqId);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function(e) {
|
document.addEventListener('DOMContentLoaded', function(e) {
|
||||||
console.log('loaded event', e)
|
|
||||||
loadDynamicPicker(document)
|
loadDynamicPicker(document)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<h4 class="h3">{{ $t('fill_an_address') }}</h4>
|
<h4 class="h3">{{ $t('fill_an_address') }}</h4>
|
||||||
<div class="row my-3">
|
<div class="row my-3">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6" v-if="!isNoAddress">
|
||||||
<div class="form-floating my-1">
|
<div class="form-floating my-1">
|
||||||
<input class="form-control"
|
<input class="form-control"
|
||||||
type="text"
|
type="text"
|
||||||
@ -35,8 +35,8 @@
|
|||||||
<label for="flat">{{ $t('flat') }}</label>
|
<label for="flat">{{ $t('flat') }}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div :class="isNoAddress ? 'col-lg-12' : 'col-lg-6'">
|
||||||
<div class="form-floating my-1">
|
<div class="form-floating my-1" v-if="!isNoAddress">
|
||||||
<input class="form-control"
|
<input class="form-control"
|
||||||
type="text"
|
type="text"
|
||||||
name="buildingName"
|
name="buildingName"
|
||||||
@ -54,7 +54,7 @@
|
|||||||
v-model="extra"/>
|
v-model="extra"/>
|
||||||
<label for="extra">{{ $t('extra') }}</label>
|
<label for="extra">{{ $t('extra') }}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-floating my-1">
|
<div class="form-floating my-1" v-if="!isNoAddress">
|
||||||
<input class="form-control"
|
<input class="form-control"
|
||||||
type="text"
|
type="text"
|
||||||
name="distribution"
|
name="distribution"
|
||||||
@ -70,7 +70,7 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "AddressMore",
|
name: "AddressMore",
|
||||||
props: ['entity'],
|
props: ['entity', 'isNoAddress'],
|
||||||
computed: {
|
computed: {
|
||||||
floor: {
|
floor: {
|
||||||
set(value) {
|
set(value) {
|
||||||
|
@ -75,8 +75,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<address-more v-if="!isNoAddress"
|
<address-more
|
||||||
v-bind:entity="entity">
|
v-bind:entity="entity"
|
||||||
|
v-bind:isNoAddress="isNoAddress">
|
||||||
</address-more>
|
</address-more>
|
||||||
|
|
||||||
<action-buttons v-if="insideModal === false"
|
<action-buttons v-if="insideModal === false"
|
||||||
|
@ -210,10 +210,10 @@ export default {
|
|||||||
let
|
let
|
||||||
type = this.type,
|
type = this.type,
|
||||||
data = {} ;
|
data = {} ;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'person':
|
case 'person':
|
||||||
data = this.$refs.castPerson.$data.person;
|
data = this.$refs.castPerson.$data.person;
|
||||||
|
console.log('person data are', data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'thirdparty':
|
case 'thirdparty':
|
||||||
@ -238,7 +238,7 @@ export default {
|
|||||||
if (typeof data.civility !== 'undefined' && null !== data.civility) {
|
if (typeof data.civility !== 'undefined' && null !== data.civility) {
|
||||||
data.civility = data.civility !== null ? {type: 'chill_main_civility', id: data.civility.id} : null;
|
data.civility = data.civility !== null ? {type: 'chill_main_civility', id: data.civility.id} : null;
|
||||||
}
|
}
|
||||||
if (typeof data.civility !== 'undefined' && null !== data.profession) {
|
if (typeof data.profession !== 'undefined' && null !== data.profession) {
|
||||||
data.profession = data.profession !== null ? {type: 'third_party_profession', id: data.profession.id} : null;
|
data.profession = data.profession !== null ? {type: 'third_party_profession', id: data.profession.id} : null;
|
||||||
}
|
}
|
||||||
// console.log('onthefly data', data);
|
// console.log('onthefly data', data);
|
||||||
|
@ -66,9 +66,18 @@ export default {
|
|||||||
translatedListOfTypes() {
|
translatedListOfTypes() {
|
||||||
let trans = [];
|
let trans = [];
|
||||||
this.types.forEach(t => {
|
this.types.forEach(t => {
|
||||||
|
if (this.$props.multiple) {
|
||||||
trans.push(appMessages.fr.pick_entity[t].toLowerCase());
|
trans.push(appMessages.fr.pick_entity[t].toLowerCase());
|
||||||
|
} else {
|
||||||
|
trans.push(appMessages.fr.pick_entity[t + '_one'].toLowerCase());
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (this.$props.multiple) {
|
||||||
return appMessages.fr.pick_entity.modal_title + trans.join(', ');
|
return appMessages.fr.pick_entity.modal_title + trans.join(', ');
|
||||||
|
} else {
|
||||||
|
return appMessages.fr.pick_entity.modal_title_one + trans.join(', ');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -79,15 +88,10 @@ export default {
|
|||||||
);
|
);
|
||||||
this.$refs.addPersons.resetSearch(); // to cast child method
|
this.$refs.addPersons.resetSearch(); // to cast child method
|
||||||
modal.showModal = false;
|
modal.showModal = false;
|
||||||
console.log(this.picked)
|
|
||||||
},
|
},
|
||||||
removeEntity(entity) {
|
removeEntity(entity) {
|
||||||
console.log('remove entity', entity);
|
|
||||||
this.$emit('removeEntity', entity);
|
this.$emit('removeEntity', entity);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
console.log(this.picked);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -11,6 +11,10 @@ const appMessages = {
|
|||||||
user: 'Utilisateurs',
|
user: 'Utilisateurs',
|
||||||
person: 'Usagers',
|
person: 'Usagers',
|
||||||
thirdparty: 'Tiers',
|
thirdparty: 'Tiers',
|
||||||
|
modal_title_one: 'Indiquer un ',
|
||||||
|
user_one: 'Utilisateur',
|
||||||
|
thirdparty_one: 'Tiers',
|
||||||
|
person_one: 'Usager',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,11 @@
|
|||||||
</p>
|
</p>
|
||||||
<p class="country">{{ address.postCode.country.name|localize_translatable_string }}</p>
|
<p class="country">{{ address.postCode.country.name|localize_translatable_string }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if address.extra is not empty %}
|
||||||
|
<span>
|
||||||
|
{{ address.extra }}
|
||||||
|
</span>
|
||||||
|
{% endif %}
|
||||||
<span class="noaddress">
|
<span class="noaddress">
|
||||||
{{ 'address.consider homeless'|trans }}
|
{{ 'address.consider homeless'|trans }}
|
||||||
</span>
|
</span>
|
||||||
@ -89,6 +94,11 @@
|
|||||||
<p class="country">{{ address.postCode.country.name|localize_translatable_string }}</p>
|
<p class="country">{{ address.postCode.country.name|localize_translatable_string }}</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if address.extra is not empty %}
|
||||||
|
<div>
|
||||||
|
{{ address.extra }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
<div class="noaddress">
|
<div class="noaddress">
|
||||||
{{ 'address.consider homeless'|trans }}
|
{{ 'address.consider homeless'|trans }}
|
||||||
</div>
|
</div>
|
||||||
|
@ -217,6 +217,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block pick_entity_dynamic_widget %}
|
{% block pick_entity_dynamic_widget %}
|
||||||
|
{{ form_help(form)}}
|
||||||
<input type="hidden" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %} data-input-uniqid="{{ form.vars['uniqid'] }}"/>
|
<input type="hidden" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %} data-input-uniqid="{{ form.vars['uniqid'] }}"/>
|
||||||
<div data-module="pick-dynamic" data-types="{{ form.vars['types']|json_encode }}" data-multiple="{{ form.vars['multiple'] }}" data-uniqid="{{ form.vars['uniqid'] }}"></div>
|
<div data-module="pick-dynamic" data-types="{{ form.vars['types']|json_encode }}" data-multiple="{{ form.vars['multiple'] }}" data-uniqid="{{ form.vars['uniqid'] }}"></div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -36,7 +36,8 @@
|
|||||||
|
|
||||||
{# Flash messages ! #}
|
{# Flash messages ! #}
|
||||||
{% if app.session.flashbag.keys()|length > 0 %}
|
{% if app.session.flashbag.keys()|length > 0 %}
|
||||||
<div class="col-8 mb-5 flash_message">
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-10 mb-5 flash_message">
|
||||||
|
|
||||||
{% for flashMessage in app.session.flashbag.get('success') %}
|
{% for flashMessage in app.session.flashbag.get('success') %}
|
||||||
<div class="alert alert-success flash_message">
|
<div class="alert alert-success flash_message">
|
||||||
@ -57,6 +58,7 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\Migrations\Main;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add 3 fields on AddressReference.
|
||||||
|
*/
|
||||||
|
final class Version20220325134944 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference DROP createdAt');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference DROP deletedAt');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference DROP updatedAt');
|
||||||
|
$this->addSql('DROP INDEX address_refid');
|
||||||
|
$this->addSql('create index address_refid
|
||||||
|
on chill_main_address_reference (refid)
|
||||||
|
where ((refid)::text <> \'\'::text)');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Add 3 fields on AddressReference';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ADD createdAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ADD deletedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE chill_main_address_reference ADD updatedAt TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
||||||
|
$this->addSql('COMMENT ON COLUMN chill_main_address_reference.createdAt IS \'(DC2Type:datetime_immutable)\'');
|
||||||
|
$this->addSql('COMMENT ON COLUMN chill_main_address_reference.deletedAt IS \'(DC2Type:datetime_immutable)\'');
|
||||||
|
$this->addSql('COMMENT ON COLUMN chill_main_address_reference.updatedAt IS \'(DC2Type:datetime_immutable)\'');
|
||||||
|
$this->addSql('DROP INDEX address_refid');
|
||||||
|
$this->addSql('CREATE INDEX address_refid ON chill_main_address_reference (refId)');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\Migrations\Main;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
final class Version20220506131307 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('DROP INDEX chill_internal_address_reference_canonicalized');
|
||||||
|
$this->addSql('create index chill_internal_address_reference_canonicalized
|
||||||
|
on chill_main_address_reference using gist (postcode_id, addresscanonical gist_trgm_ops);');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Adapt search index on address reference canonicalized';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('DROP INDEX chill_internal_address_reference_canonicalized');
|
||||||
|
$this->addSql('create index chill_internal_address_reference_canonicalized
|
||||||
|
on chill_main_address_reference using gist (postcode_id, addresscanonical gist_trgm_ops) WHERE deletedat IS NULL;');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Chill\Migrations\Main;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
final class Version20220506145935 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('DROP INDEX search_by_reference_code');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'Add index to search postal code by references';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('CREATE INDEX search_by_reference_code ON chill_main_postal_code (code, refpostalcodeid)');
|
||||||
|
}
|
||||||
|
}
|
@ -247,7 +247,7 @@ final class AccompanyingCourseApiController extends ApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (null === $requestor) {
|
if (null === $requestor) {
|
||||||
throw new BadRequestHttpException('Could not find any person or thirdparty', 0, null);
|
throw new BadRequestHttpException('Could not find any person or thirdparty');
|
||||||
}
|
}
|
||||||
|
|
||||||
$accompanyingPeriod->setRequestor($requestor);
|
$accompanyingPeriod->setRequestor($requestor);
|
||||||
|
@ -12,12 +12,15 @@ declare(strict_types=1);
|
|||||||
namespace Chill\PersonBundle\Controller;
|
namespace Chill\PersonBundle\Controller;
|
||||||
|
|
||||||
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
|
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
|
||||||
|
use Chill\PersonBundle\Entity\Household\Household;
|
||||||
|
use Chill\PersonBundle\Entity\Household\HouseholdMember;
|
||||||
use Chill\PersonBundle\Entity\Person;
|
use Chill\PersonBundle\Entity\Person;
|
||||||
use Chill\PersonBundle\Form\CreationPersonType;
|
use Chill\PersonBundle\Form\CreationPersonType;
|
||||||
use Chill\PersonBundle\Form\PersonType;
|
use Chill\PersonBundle\Form\PersonType;
|
||||||
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
use Chill\PersonBundle\Privacy\PrivacyEvent;
|
||||||
use Chill\PersonBundle\Repository\PersonRepository;
|
use Chill\PersonBundle\Repository\PersonRepository;
|
||||||
use Chill\PersonBundle\Search\SimilarPersonMatcher;
|
use Chill\PersonBundle\Search\SimilarPersonMatcher;
|
||||||
|
use DateTimeImmutable;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
|
||||||
@ -31,8 +34,8 @@ use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
|||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
use Symfony\Component\Security\Core\Security;
|
use Symfony\Component\Security\Core\Security;
|
||||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
|
||||||
|
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
use function count;
|
use function count;
|
||||||
use function hash;
|
use function hash;
|
||||||
use function implode;
|
use function implode;
|
||||||
@ -248,6 +251,31 @@ final class PersonController extends AbstractController
|
|||||||
$this->em->flush();
|
$this->em->flush();
|
||||||
$this->lastPostDataReset();
|
$this->lastPostDataReset();
|
||||||
|
|
||||||
|
$address = $form->get('address')->getData();
|
||||||
|
$addressForm = (bool) $form->get('addressForm')->getData();
|
||||||
|
|
||||||
|
if (null !== $address && $addressForm) {
|
||||||
|
$household = new Household();
|
||||||
|
|
||||||
|
$member = new HouseholdMember();
|
||||||
|
$member->setPerson($person);
|
||||||
|
$member->setStartDate(new DateTimeImmutable());
|
||||||
|
|
||||||
|
$household->addMember($member);
|
||||||
|
$household->setForceAddress($address);
|
||||||
|
|
||||||
|
$this->em->persist($member);
|
||||||
|
$this->em->persist($household);
|
||||||
|
$this->em->flush();
|
||||||
|
|
||||||
|
if ($form->get('createHousehold')->isClicked()) {
|
||||||
|
return $this->redirectToRoute('chill_person_household_members_editor', [
|
||||||
|
'persons' => [$person->getId()],
|
||||||
|
'household' => $household->getId(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($form->get('createPeriod')->isClicked()) {
|
if ($form->get('createPeriod')->isClicked()) {
|
||||||
return $this->redirectToRoute('chill_person_accompanying_course_new', [
|
return $this->redirectToRoute('chill_person_accompanying_course_new', [
|
||||||
'person_id' => [$person->getId()],
|
'person_id' => [$person->getId()],
|
||||||
|
@ -12,13 +12,18 @@ declare(strict_types=1);
|
|||||||
namespace Chill\PersonBundle\Controller;
|
namespace Chill\PersonBundle\Controller;
|
||||||
|
|
||||||
use Chill\MainBundle\Entity\User;
|
use Chill\MainBundle\Entity\User;
|
||||||
|
use Chill\MainBundle\Form\Type\PickUserDynamicType;
|
||||||
use Chill\MainBundle\Pagination\PaginatorFactory;
|
use Chill\MainBundle\Pagination\PaginatorFactory;
|
||||||
use Chill\MainBundle\Repository\UserRepository;
|
use Chill\MainBundle\Repository\UserRepository;
|
||||||
use Chill\MainBundle\Templating\Entity\UserRender;
|
use Chill\MainBundle\Templating\Entity\UserRender;
|
||||||
use Chill\PersonBundle\Repository\AccompanyingPeriodACLAwareRepositoryInterface;
|
use Chill\PersonBundle\Repository\AccompanyingPeriodACLAwareRepositoryInterface;
|
||||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
use Chill\PersonBundle\Repository\AccompanyingPeriodRepository;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\Form\CallbackTransformer;
|
||||||
|
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||||
use Symfony\Component\Form\FormFactoryInterface;
|
use Symfony\Component\Form\FormFactoryInterface;
|
||||||
use Symfony\Component\Form\FormInterface;
|
use Symfony\Component\Form\FormInterface;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
@ -27,11 +32,18 @@ use Symfony\Component\Routing\Annotation\Route;
|
|||||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||||
use Symfony\Component\Security\Core\Security;
|
use Symfony\Component\Security\Core\Security;
|
||||||
use Symfony\Component\Templating\EngineInterface;
|
use Symfony\Component\Templating\EngineInterface;
|
||||||
|
use Symfony\Component\Validator\Constraints\NotIdenticalTo;
|
||||||
|
use Symfony\Component\Validator\Constraints\NotNull;
|
||||||
|
use function is_int;
|
||||||
|
|
||||||
class ReassignAccompanyingPeriodController extends AbstractController
|
class ReassignAccompanyingPeriodController extends AbstractController
|
||||||
{
|
{
|
||||||
private AccompanyingPeriodACLAwareRepositoryInterface $accompanyingPeriodACLAwareRepository;
|
private AccompanyingPeriodACLAwareRepositoryInterface $accompanyingPeriodACLAwareRepository;
|
||||||
|
|
||||||
|
private AccompanyingPeriodRepository $courseRepository;
|
||||||
|
|
||||||
|
private EntityManagerInterface $em;
|
||||||
|
|
||||||
private EngineInterface $engine;
|
private EngineInterface $engine;
|
||||||
|
|
||||||
private FormFactoryInterface $formFactory;
|
private FormFactoryInterface $formFactory;
|
||||||
@ -44,8 +56,17 @@ class ReassignAccompanyingPeriodController extends AbstractController
|
|||||||
|
|
||||||
private UserRepository $userRepository;
|
private UserRepository $userRepository;
|
||||||
|
|
||||||
public function __construct(AccompanyingPeriodACLAwareRepositoryInterface $accompanyingPeriodACLAwareRepository, UserRepository $userRepository, EngineInterface $engine, FormFactoryInterface $formFactory, PaginatorFactory $paginatorFactory, Security $security, UserRender $userRender)
|
public function __construct(
|
||||||
{
|
AccompanyingPeriodACLAwareRepositoryInterface $accompanyingPeriodACLAwareRepository,
|
||||||
|
UserRepository $userRepository,
|
||||||
|
AccompanyingPeriodRepository $courseRepository,
|
||||||
|
EngineInterface $engine,
|
||||||
|
FormFactoryInterface $formFactory,
|
||||||
|
PaginatorFactory $paginatorFactory,
|
||||||
|
Security $security,
|
||||||
|
UserRender $userRender,
|
||||||
|
EntityManagerInterface $em
|
||||||
|
) {
|
||||||
$this->accompanyingPeriodACLAwareRepository = $accompanyingPeriodACLAwareRepository;
|
$this->accompanyingPeriodACLAwareRepository = $accompanyingPeriodACLAwareRepository;
|
||||||
$this->engine = $engine;
|
$this->engine = $engine;
|
||||||
$this->formFactory = $formFactory;
|
$this->formFactory = $formFactory;
|
||||||
@ -53,6 +74,8 @@ class ReassignAccompanyingPeriodController extends AbstractController
|
|||||||
$this->security = $security;
|
$this->security = $security;
|
||||||
$this->userRepository = $userRepository;
|
$this->userRepository = $userRepository;
|
||||||
$this->userRender = $userRender;
|
$this->userRender = $userRender;
|
||||||
|
$this->courseRepository = $courseRepository;
|
||||||
|
$this->em = $em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,23 +91,55 @@ class ReassignAccompanyingPeriodController extends AbstractController
|
|||||||
|
|
||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
|
|
||||||
$total = $this->accompanyingPeriodACLAwareRepository->countByUserOpenedAccompanyingPeriod(
|
$userFrom = $form['user']->getData();
|
||||||
$form['user']->getData()
|
|
||||||
);
|
$total = $this->accompanyingPeriodACLAwareRepository->countByUserOpenedAccompanyingPeriod($userFrom);
|
||||||
$paginator = $this->paginatorFactory->create($total);
|
$paginator = $this->paginatorFactory->create($total);
|
||||||
$periods = $this->accompanyingPeriodACLAwareRepository
|
$periods = $this->accompanyingPeriodACLAwareRepository
|
||||||
->findByUserOpenedAccompanyingPeriod(
|
->findByUserOpenedAccompanyingPeriod(
|
||||||
$form['user']->getData(),
|
$userFrom,
|
||||||
['openingDate' => 'ASC'],
|
['openingDate' => 'ASC'],
|
||||||
$paginator->getItemsPerPage(),
|
$paginator->getItemsPerPage(),
|
||||||
$paginator->getCurrentPageFirstItemNumber()
|
$paginator->getCurrentPageFirstItemNumber()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$periodIds = [];
|
||||||
|
|
||||||
|
foreach ($periods as $period) {
|
||||||
|
$periodIds[] = $period->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an array of period id's to pass into assignForm hiddenfield
|
||||||
|
$assignForm = $this->buildReassignForm($periodIds, $userFrom);
|
||||||
|
|
||||||
|
$assignForm->handleRequest($request);
|
||||||
|
|
||||||
|
if ($assignForm->isSubmitted() && $assignForm->isValid()) {
|
||||||
|
$assignPeriodIds = json_decode($assignForm->get('periods')->getData(), true);
|
||||||
|
$userTo = $assignForm->get('userTo')->getData();
|
||||||
|
$userFrom = $assignForm->get('userFrom')->getData();
|
||||||
|
|
||||||
|
foreach ($assignPeriodIds as $periodId) {
|
||||||
|
$period = $this->courseRepository->find($periodId);
|
||||||
|
|
||||||
|
if ($period->getUser() === $userFrom) {
|
||||||
|
$period->setUser($userTo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->em->flush();
|
||||||
|
|
||||||
|
// redirect to the first page
|
||||||
|
return $this->redirectToRoute('chill_course_list_reassign', $request->query->all());
|
||||||
|
}
|
||||||
|
|
||||||
return new Response(
|
return new Response(
|
||||||
$this->engine->render('@ChillPerson/AccompanyingPeriod/reassign_list.html.twig', [
|
$this->engine->render('@ChillPerson/AccompanyingPeriod/reassign_list.html.twig', [
|
||||||
|
'assignForm' => $assignForm->createView(),
|
||||||
|
'form' => $form->createView(),
|
||||||
'paginator' => $paginator,
|
'paginator' => $paginator,
|
||||||
'periods' => $periods,
|
'periods' => $periods,
|
||||||
'form' => $form->createView(),
|
'userFrom' => $userFrom,
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -98,17 +153,63 @@ class ReassignAccompanyingPeriodController extends AbstractController
|
|||||||
'method' => 'get', 'csrf_protection' => false, ]);
|
'method' => 'get', 'csrf_protection' => false, ]);
|
||||||
|
|
||||||
$builder
|
$builder
|
||||||
->add('user', EntityType::class, [
|
->add('user', PickUserDynamicType::class, [
|
||||||
'class' => User::class,
|
|
||||||
'choices' => $this->userRepository->findByActive(['username' => 'ASC']),
|
|
||||||
'choice_label' => function (User $u) {
|
|
||||||
return $this->userRender->renderString($u, []);
|
|
||||||
},
|
|
||||||
'multiple' => false,
|
'multiple' => false,
|
||||||
'label' => 'User',
|
'label' => 'reassign.Current user',
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'help' => 'reassign.Choose a user and click on "Filter" to apply',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $builder->getForm();
|
return $builder->getForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function buildReassignForm(array $periodIds, ?User $userFrom): FormInterface
|
||||||
|
{
|
||||||
|
$defaultData = [
|
||||||
|
'userFrom' => $userFrom,
|
||||||
|
'periods' => json_encode($periodIds),
|
||||||
|
];
|
||||||
|
|
||||||
|
$builder = $this->formFactory->createNamedBuilder('reassign', FormType::class, $defaultData);
|
||||||
|
|
||||||
|
if (null !== $userFrom) {
|
||||||
|
$constraints = [new NotIdenticalTo(['value' => $userFrom])];
|
||||||
|
} else {
|
||||||
|
$constraints = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$builder
|
||||||
|
->add('periods', HiddenType::class)
|
||||||
|
->add('userFrom', HiddenType::class)
|
||||||
|
->add('userTo', PickUserDynamicType::class, [
|
||||||
|
'multiple' => false,
|
||||||
|
'label' => 'reassign.Next user',
|
||||||
|
'required' => true,
|
||||||
|
'help' => 'reassign.All periods on this list will be reassigned to this user, excepted the one you manually reassigned before',
|
||||||
|
'constraints' => [new NotNull()],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$builder->get('userFrom')->addModelTransformer(new CallbackTransformer(
|
||||||
|
static function (?User $user) {
|
||||||
|
if (null === $user) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $user->getId();
|
||||||
|
},
|
||||||
|
function (?string $id) {
|
||||||
|
if (null === $id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_int((int) $id)) {
|
||||||
|
throw new TransformationFailedException('the user id is not a numeric');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->userRepository->find((int) $id);
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
return $builder->getForm();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ use Doctrine\Common\DataFixtures\DependentFixtureInterface;
|
|||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\Persistence\ObjectManager;
|
use Doctrine\Persistence\ObjectManager;
|
||||||
|
|
||||||
|
use function array_key_exists;
|
||||||
use function count;
|
use function count;
|
||||||
|
|
||||||
class LoadRelationships extends Fixture implements DependentFixtureInterface
|
class LoadRelationships extends Fixture implements DependentFixtureInterface
|
||||||
@ -34,7 +35,7 @@ class LoadRelationships extends Fixture implements DependentFixtureInterface
|
|||||||
$this->em = $em;
|
$this->em = $em;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDependencies()
|
public function getDependencies(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
LoadPeople::class,
|
LoadPeople::class,
|
||||||
@ -42,9 +43,11 @@ class LoadRelationships extends Fixture implements DependentFixtureInterface
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function load(ObjectManager $manager)
|
public function load(ObjectManager $manager): void
|
||||||
{
|
{
|
||||||
for ($i = 0; 15 > $i; ++$i) {
|
$existing = [];
|
||||||
|
|
||||||
|
for ($i = 0; 20 > $i; ++$i) {
|
||||||
$user = $this->getRandomUser();
|
$user = $this->getRandomUser();
|
||||||
$date = new DateTimeImmutable();
|
$date = new DateTimeImmutable();
|
||||||
$relationship = (new Relationship())
|
$relationship = (new Relationship())
|
||||||
@ -57,6 +60,17 @@ class LoadRelationships extends Fixture implements DependentFixtureInterface
|
|||||||
->setUpdatedBy($user)
|
->setUpdatedBy($user)
|
||||||
->setCreatedAt($date)
|
->setCreatedAt($date)
|
||||||
->setUpdatedAt($date);
|
->setUpdatedAt($date);
|
||||||
|
|
||||||
|
// remove the potential duplicates
|
||||||
|
$set = $relationship->getFromPerson()->getId() < $relationship->getToPerson()->getId() ?
|
||||||
|
[$relationship->getFromPerson()->getId(), $relationship->getToPerson()->getId()] :
|
||||||
|
[$relationship->getToPerson()->getId(), $relationship->getFromPerson()->getId()];
|
||||||
|
|
||||||
|
if (array_key_exists($set[0], $existing) && array_key_exists($set[1], $existing[$set[0]])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$existing[$set[0]][$existing[$set[1]]] = 1;
|
||||||
$manager->persist($relationship);
|
$manager->persist($relationship);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,6 +639,7 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
|||||||
'methods' => [
|
'methods' => [
|
||||||
Request::METHOD_GET => true,
|
Request::METHOD_GET => true,
|
||||||
Request::METHOD_HEAD => true,
|
Request::METHOD_HEAD => true,
|
||||||
|
Request::METHOD_POST => true,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'suggestHouseholdByAccompanyingPeriodParticipation' => [
|
'suggestHouseholdByAccompanyingPeriodParticipation' => [
|
||||||
@ -957,6 +958,12 @@ class ChillPersonExtension extends Extension implements PrependExtensionInterfac
|
|||||||
AccompanyingPeriodVoter::EDIT,
|
AccompanyingPeriodVoter::EDIT,
|
||||||
AccompanyingPeriodVoter::DELETE,
|
AccompanyingPeriodVoter::DELETE,
|
||||||
],
|
],
|
||||||
|
AccompanyingPeriodVoter::REASSIGN_BULK => [
|
||||||
|
AccompanyingPeriodVoter::CONFIDENTIAL_CRUD,
|
||||||
|
],
|
||||||
|
AccompanyingPeriodVoter::TOGGLE_CONFIDENTIAL => [
|
||||||
|
AccompanyingPeriodVoter::CONFIDENTIAL_CRUD,
|
||||||
|
],
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ class HouseholdMember
|
|||||||
/**
|
/**
|
||||||
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
|
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
|
||||||
* @Serializer\Groups({"read", "docgen:read"})
|
* @Serializer\Groups({"read", "docgen:read"})
|
||||||
* @Assert\GreaterThan(
|
* @Assert\GreaterThanOrEqual(
|
||||||
* propertyPath="startDate",
|
* propertyPath="startDate",
|
||||||
* message="household_membership.The end date must be after start date",
|
* message="household_membership.The end date must be after start date",
|
||||||
* groups={"household_memberships"}
|
* groups={"household_memberships"}
|
||||||
@ -82,14 +82,13 @@ class HouseholdMember
|
|||||||
/**
|
/**
|
||||||
* @ORM\ManyToOne(targetEntity=Position::class)
|
* @ORM\ManyToOne(targetEntity=Position::class)
|
||||||
* @Serializer\Groups({"read", "docgen:read"})
|
* @Serializer\Groups({"read", "docgen:read"})
|
||||||
* @Assert\NotNull(groups={"household_memberships_created"})
|
|
||||||
*/
|
*/
|
||||||
private ?Position $position = null;
|
private ?Position $position = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="boolean", name="sharedhousehold")
|
* @ORM\Column(type="boolean", name="sharedhousehold")
|
||||||
*/
|
*/
|
||||||
private bool $shareHousehold = false;
|
private bool $shareHousehold = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
|
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
|
||||||
@ -201,15 +200,18 @@ class HouseholdMember
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setPosition(Position $position): self
|
public function setPosition(?Position $position): self
|
||||||
{
|
{
|
||||||
if ($this->position instanceof Position) {
|
if ($this->position instanceof Position && $this->position !== $position) {
|
||||||
throw new LogicException('The position is already set. You cannot change ' .
|
throw new LogicException('The position is already set. You cannot change ' .
|
||||||
'a position of a membership');
|
'a position of a membership');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->position = $position;
|
$this->position = $position;
|
||||||
|
|
||||||
|
if (null !== $position) {
|
||||||
$this->shareHousehold = $position->getShareHousehold();
|
$this->shareHousehold = $position->getShareHousehold();
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,13 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\PersonBundle\Form;
|
namespace Chill\PersonBundle\Form;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Address;
|
||||||
use Chill\MainBundle\Form\Event\CustomizeFormEvent;
|
use Chill\MainBundle\Form\Event\CustomizeFormEvent;
|
||||||
use Chill\MainBundle\Form\Type\ChillDateType;
|
use Chill\MainBundle\Form\Type\ChillDateType;
|
||||||
use Chill\MainBundle\Form\Type\ChillPhoneNumberType;
|
use Chill\MainBundle\Form\Type\ChillPhoneNumberType;
|
||||||
|
use Chill\MainBundle\Form\Type\PickAddressType;
|
||||||
use Chill\MainBundle\Form\Type\PickCenterType;
|
use Chill\MainBundle\Form\Type\PickCenterType;
|
||||||
|
use Chill\MainBundle\Form\Type\PickCivilityType;
|
||||||
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
|
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
|
||||||
use Chill\PersonBundle\Entity\Person;
|
use Chill\PersonBundle\Entity\Person;
|
||||||
use Chill\PersonBundle\Form\Type\GenderType;
|
use Chill\PersonBundle\Form\Type\GenderType;
|
||||||
@ -24,9 +27,12 @@ use libphonenumber\PhoneNumberType;
|
|||||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||||
use Symfony\Component\Form\FormBuilderInterface;
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use Symfony\Component\Validator\Constraints\Callback;
|
||||||
|
use Symfony\Component\Validator\Context\ExecutionContextInterface;
|
||||||
|
|
||||||
final class CreationPersonType extends AbstractType
|
final class CreationPersonType extends AbstractType
|
||||||
{
|
{
|
||||||
@ -55,6 +61,11 @@ final class CreationPersonType extends AbstractType
|
|||||||
$builder
|
$builder
|
||||||
->add('firstName')
|
->add('firstName')
|
||||||
->add('lastName')
|
->add('lastName')
|
||||||
|
->add('civility', PickCivilityType::class, [
|
||||||
|
'required' => false,
|
||||||
|
'label' => 'Civility',
|
||||||
|
'placeholder' => 'choose civility',
|
||||||
|
])
|
||||||
->add('gender', GenderType::class, [
|
->add('gender', GenderType::class, [
|
||||||
'required' => true, 'placeholder' => null,
|
'required' => true, 'placeholder' => null,
|
||||||
])
|
])
|
||||||
@ -71,6 +82,17 @@ final class CreationPersonType extends AbstractType
|
|||||||
])
|
])
|
||||||
->add('email', EmailType::class, [
|
->add('email', EmailType::class, [
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
])
|
||||||
|
->add('addressForm', CheckboxType::class, [
|
||||||
|
'label' => 'Create a household and add an address',
|
||||||
|
'required' => false,
|
||||||
|
'mapped' => false,
|
||||||
|
'help' => 'A new household will be created. The person will be member of this household.',
|
||||||
|
])
|
||||||
|
->add('address', PickAddressType::class, [
|
||||||
|
'required' => false,
|
||||||
|
'mapped' => false,
|
||||||
|
'label' => false,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if ($this->askCenters) {
|
if ($this->askCenters) {
|
||||||
@ -97,6 +119,9 @@ final class CreationPersonType extends AbstractType
|
|||||||
{
|
{
|
||||||
$resolver->setDefaults([
|
$resolver->setDefaults([
|
||||||
'data_class' => Person::class,
|
'data_class' => Person::class,
|
||||||
|
'constraints' => [
|
||||||
|
new Callback([$this, 'validateCheckedAddress']),
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,4 +132,18 @@ final class CreationPersonType extends AbstractType
|
|||||||
{
|
{
|
||||||
return self::NAME;
|
return self::NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function validateCheckedAddress($data, ExecutionContextInterface $context, $payload): void
|
||||||
|
{
|
||||||
|
/** @var bool $addressFrom */
|
||||||
|
$addressFrom = $context->getObject()->get('addressForm')->getData();
|
||||||
|
/** @var ?Address $address */
|
||||||
|
$address = $context->getObject()->get('address')->getData();
|
||||||
|
|
||||||
|
if ($addressFrom && null === $address) {
|
||||||
|
$context->buildViolation('person_creation.If you want to create an household, an address is required')
|
||||||
|
->atPath('addressForm')
|
||||||
|
->addViolation();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,12 +26,15 @@ class HouseholdMemberType extends AbstractType
|
|||||||
'input' => 'datetime_immutable',
|
'input' => 'datetime_immutable',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (null !== $options['data']->getPosition()) {
|
||||||
if (!$options['data']->getPosition()->getShareHousehold()) {
|
if (!$options['data']->getPosition()->getShareHousehold()) {
|
||||||
$builder->add('endDate', ChillDateType::class, [
|
$builder->add('endDate', ChillDateType::class, [
|
||||||
'label' => 'household.End date',
|
'label' => 'household.End date',
|
||||||
'input' => 'datetime_immutable',
|
'input' => 'datetime_immutable',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$builder
|
$builder
|
||||||
->add('comment', ChillTextareaType::class, [
|
->add('comment', ChillTextareaType::class, [
|
||||||
'label' => 'household.Comment',
|
'label' => 'household.Comment',
|
||||||
|
@ -55,7 +55,7 @@ class MembersEditor
|
|||||||
$this->eventDispatcher = $eventDispatcher;
|
$this->eventDispatcher = $eventDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addMovement(DateTimeImmutable $date, Person $person, Position $position, ?bool $holder = false, ?string $comment = null): self
|
public function addMovement(DateTimeImmutable $date, Person $person, ?Position $position, ?bool $holder = false, ?string $comment = null): self
|
||||||
{
|
{
|
||||||
if (null === $this->household) {
|
if (null === $this->household) {
|
||||||
throw new LogicException('You must define a household first');
|
throw new LogicException('You must define a household first');
|
||||||
@ -69,6 +69,7 @@ class MembersEditor
|
|||||||
->setComment($comment);
|
->setComment($comment);
|
||||||
$this->household->addMember($membership);
|
$this->household->addMember($membership);
|
||||||
|
|
||||||
|
if (null !== $position) {
|
||||||
if ($position->getShareHousehold()) {
|
if ($position->getShareHousehold()) {
|
||||||
// launch event only if moving to a "share household" position,
|
// launch event only if moving to a "share household" position,
|
||||||
// and if the destination household is different than the previous one
|
// and if the destination household is different than the previous one
|
||||||
@ -134,6 +135,7 @@ class MembersEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->membershipsAffected[] = $membership;
|
$this->membershipsAffected[] = $membership;
|
||||||
$this->persistables[] = $membership;
|
$this->persistables[] = $membership;
|
||||||
|
@ -12,6 +12,7 @@ declare(strict_types=1);
|
|||||||
namespace Chill\PersonBundle\Menu;
|
namespace Chill\PersonBundle\Menu;
|
||||||
|
|
||||||
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
use Chill\MainBundle\Routing\LocalMenuBuilderInterface;
|
||||||
|
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodVoter;
|
||||||
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
use Chill\PersonBundle\Security\Authorization\PersonVoter;
|
||||||
use Knp\Menu\MenuItem;
|
use Knp\Menu\MenuItem;
|
||||||
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
|
||||||
@ -64,14 +65,16 @@ class SectionMenuBuilder implements LocalMenuBuilderInterface
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$menu->addChild($this->translator->trans('Accompanying courses of users'), [
|
if ($this->authorizationChecker->isGranted(AccompanyingPeriodVoter::REASSIGN_BULK, null)) {
|
||||||
|
$menu->addChild($this->translator->trans('reassign.Bulk reassign'), [
|
||||||
'route' => 'chill_course_list_reassign',
|
'route' => 'chill_course_list_reassign',
|
||||||
])
|
])
|
||||||
->setExtras([
|
->setExtras([
|
||||||
'order' => 12,
|
'order' => 40,
|
||||||
'icons' => ['task'],
|
'icons' => [],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static function getMenuIds(): array
|
public static function getMenuIds(): array
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
import { ShowHide } from 'ShowHide';
|
||||||
|
|
||||||
|
const addressForm = document.getElementById("addressForm");
|
||||||
|
const address = document.getElementById("address");
|
||||||
|
|
||||||
|
new ShowHide({
|
||||||
|
froms: [addressForm],
|
||||||
|
container: [address],
|
||||||
|
test: function(froms) {
|
||||||
|
for (let f of froms.values()) {
|
||||||
|
for (let input of f.querySelectorAll('input').values()) {
|
||||||
|
return input.checked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
event_name: 'change'
|
||||||
|
});
|
@ -123,6 +123,7 @@ export default {
|
|||||||
body.email = payload.data.email;
|
body.email = payload.data.email;
|
||||||
body.altNames = payload.data.altNames;
|
body.altNames = payload.data.altNames;
|
||||||
body.gender = payload.data.gender;
|
body.gender = payload.data.gender;
|
||||||
|
if (payload.data.civility !== null) { body.civility = {id: payload.data.civility.id, type: payload.data.civility.type }; }
|
||||||
|
|
||||||
makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body)
|
makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
|
@ -150,6 +150,7 @@ export default {
|
|||||||
body.email = payload.data.email;
|
body.email = payload.data.email;
|
||||||
body.altNames = payload.data.altNames;
|
body.altNames = payload.data.altNames;
|
||||||
body.gender = payload.data.gender;
|
body.gender = payload.data.gender;
|
||||||
|
if (payload.data.civility !== null) { body.civility = {id: payload.data.civility.id, type: payload.data.civility.type}; }
|
||||||
|
|
||||||
makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body)
|
makeFetch('PATCH', `/api/1.0/person/person/${payload.data.id}.json`, body)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
|
@ -14,8 +14,13 @@ const getPersonAltNames = () =>
|
|||||||
fetch('/api/1.0/person/config/alt_names.json').then(response => {
|
fetch('/api/1.0/person/config/alt_names.json').then(response => {
|
||||||
if (response.ok) { return response.json(); }
|
if (response.ok) { return response.json(); }
|
||||||
throw Error('Error with request resource response');
|
throw Error('Error with request resource response');
|
||||||
});;
|
});
|
||||||
|
|
||||||
|
const getCivilities = () =>
|
||||||
|
fetch('/api/1.0/main/civility.json').then(response => {
|
||||||
|
if (response.ok) { return response.json(); }
|
||||||
|
throw Error('Error with request resource response');
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* POST a new person
|
* POST a new person
|
||||||
@ -56,6 +61,7 @@ const patchPerson = (id, body) => {
|
|||||||
export {
|
export {
|
||||||
getPerson,
|
getPerson,
|
||||||
getPersonAltNames,
|
getPersonAltNames,
|
||||||
|
getCivilities,
|
||||||
postPerson,
|
postPerson,
|
||||||
patchPerson
|
patchPerson
|
||||||
};
|
};
|
||||||
|
@ -277,12 +277,58 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
saveFormOnTheFly({ type, data }) {
|
saveFormOnTheFly({ type, data }) {
|
||||||
// console.log('saveFormOnTheFly from addPersons, type', type, ', data', data);
|
console.log('saveFormOnTheFly from addPersons, type', type, ', data', data);
|
||||||
if (type === 'person') {
|
if (type === 'person') {
|
||||||
|
|
||||||
makeFetch('POST', '/api/1.0/person/person.json', data)
|
makeFetch('POST', '/api/1.0/person/person.json', data)
|
||||||
.then(response => {
|
.then(responsePerson => {
|
||||||
this.newPriorSuggestion(response);
|
|
||||||
|
this.newPriorSuggestion(responsePerson);
|
||||||
this.$refs.onTheFly.closeModal();
|
this.$refs.onTheFly.closeModal();
|
||||||
|
|
||||||
|
if (null !== data.addressId) {
|
||||||
|
const household = {
|
||||||
|
'type': 'household'
|
||||||
|
};
|
||||||
|
const address = {
|
||||||
|
'id': data.addressId
|
||||||
|
};
|
||||||
|
makeFetch('POST', '/api/1.0/person/household.json', household)
|
||||||
|
.then(responseHousehold => {
|
||||||
|
const member = {
|
||||||
|
'concerned': [
|
||||||
|
{
|
||||||
|
'person': {
|
||||||
|
'type': 'person',
|
||||||
|
'id': responsePerson.id
|
||||||
|
},
|
||||||
|
'start_date': {
|
||||||
|
// TODO: use date.js methods (low priority)
|
||||||
|
'datetime': `${new Date().toISOString().split('T')[0]}T00:00:00+02:00`
|
||||||
|
},
|
||||||
|
'holder': false,
|
||||||
|
'comment': null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'destination': {
|
||||||
|
'type': 'household',
|
||||||
|
'id': responseHousehold.id
|
||||||
|
},
|
||||||
|
'composition': null
|
||||||
|
};
|
||||||
|
return makeFetch('POST', '/api/1.0/person/household/members/move.json', member)
|
||||||
|
.then(_response => {
|
||||||
|
makeFetch('POST', `/api/1.0/person/household/${responseHousehold.id}/address.json`, address)
|
||||||
|
.then(_response => {})
|
||||||
|
.catch((error) => {
|
||||||
|
if (error.name === 'ValidationException') {
|
||||||
|
for (let v of error.violations) {
|
||||||
|
this.$toast.open({message: v });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$toast.open({message: 'An error occurred'});
|
||||||
|
}
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
if (error.name === 'ValidationException') {
|
if (error.name === 'ValidationException') {
|
||||||
@ -292,7 +338,29 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
this.$toast.open({message: 'An error occurred'});
|
this.$toast.open({message: 'An error occurred'});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
if (error.name === 'ValidationException') {
|
||||||
|
for (let v of error.violations) {
|
||||||
|
this.$toast.open({message: v });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$toast.open({message: 'An error occurred'});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
if (error.name === 'ValidationException') {
|
||||||
|
for (let v of error.violations) {
|
||||||
|
this.$toast.open({message: v });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$toast.open({message: 'An error occurred'});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (type === 'thirdparty') {
|
else if (type === 'thirdparty') {
|
||||||
makeFetch('POST', '/api/1.0/thirdparty/thirdparty.json', data)
|
makeFetch('POST', '/api/1.0/thirdparty/thirdparty.json', data)
|
||||||
|
@ -87,6 +87,20 @@
|
|||||||
<label>{{ $t('person.gender.title') }}</label>
|
<label>{{ $t('person.gender.title') }}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-floating mb-3">
|
||||||
|
<select
|
||||||
|
class="form-select form-select-lg"
|
||||||
|
id="civility"
|
||||||
|
v-model="civility"
|
||||||
|
>
|
||||||
|
<option selected disabled >{{ $t('person.civility.placeholder') }}</option>
|
||||||
|
<option v-for="c in config.civilities" :value="c.id" :key="c.id">
|
||||||
|
{{ c.name.fr }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<label>{{ $t('person.civility.title') }}</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="input-group mb-3">
|
<div class="input-group mb-3">
|
||||||
<span class="input-group-text" id="birthdate"><i class="fa fa-fw fa-birthday-cake"></i></span>
|
<span class="input-group-text" id="birthdate"><i class="fa fa-fw fa-birthday-cake"></i></span>
|
||||||
<input type="date"
|
<input type="date"
|
||||||
@ -124,6 +138,24 @@
|
|||||||
aria-describedby="email" />
|
aria-describedby="email" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div v-if="action === 'create'" class="input-group mb-3 form-check">
|
||||||
|
<input class="form-check-input"
|
||||||
|
type='checkbox'
|
||||||
|
v-model="showAddressForm"
|
||||||
|
name='showAddressForm'/>
|
||||||
|
<label class="form-check-label">{{ $t('person.address.show_address_form') }}</label>
|
||||||
|
</div>
|
||||||
|
<div v-if="action === 'create' && showAddressFormValue" class="form-floating mb-3">
|
||||||
|
<p>{{ $t('person.address.warning') }}</p>
|
||||||
|
<add-address
|
||||||
|
:context="addAddress.context"
|
||||||
|
:options="addAddress.options"
|
||||||
|
:addressChangedCallback="submitNewAddress"
|
||||||
|
ref="addAddress">
|
||||||
|
</add-address>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="alert alert-warning" v-if="errors.length">
|
<div class="alert alert-warning" v-if="errors.length">
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="(e, i) in errors" :key="i">{{ e }}</li>
|
<li v-for="(e, i) in errors" :key="i">{{ e }}</li>
|
||||||
@ -134,24 +166,43 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getPerson, getPersonAltNames } from '../../_api/OnTheFly';
|
import { getCivilities, getPerson, getPersonAltNames } from '../../_api/OnTheFly';
|
||||||
import PersonRenderBox from '../Entity/PersonRenderBox.vue';
|
import PersonRenderBox from '../Entity/PersonRenderBox.vue';
|
||||||
|
import AddAddress from "ChillMainAssets/vuejs/Address/components/AddAddress.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "OnTheFlyPerson",
|
name: "OnTheFlyPerson",
|
||||||
props: ['id', 'type', 'action', 'query'],
|
props: ['id', 'type', 'action', 'query'],
|
||||||
//emits: ['createAction'],
|
//emits: ['createAction'],
|
||||||
components: {
|
components: {
|
||||||
PersonRenderBox
|
PersonRenderBox,
|
||||||
|
AddAddress
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
person: {
|
person: {
|
||||||
type: 'person',
|
type: 'person',
|
||||||
altNames: []
|
altNames: [],
|
||||||
|
addressId: null
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
altNames: []
|
altNames: [],
|
||||||
|
civilities: []
|
||||||
|
},
|
||||||
|
showAddressFormValue: false,
|
||||||
|
addAddress: {
|
||||||
|
options: {
|
||||||
|
button: {
|
||||||
|
text: { create: 'person.address.create_address' },
|
||||||
|
size: 'btn-sm'
|
||||||
|
},
|
||||||
|
title: { create: 'person.address.create_address' },
|
||||||
|
},
|
||||||
|
context: {
|
||||||
|
target: {}, // boilerplate for getting the address id
|
||||||
|
edit: false,
|
||||||
|
addressId: null
|
||||||
|
}
|
||||||
},
|
},
|
||||||
errors: []
|
errors: []
|
||||||
}
|
}
|
||||||
@ -171,6 +222,10 @@ export default {
|
|||||||
set(value) { this.person.gender = value; },
|
set(value) { this.person.gender = value; },
|
||||||
get() { return this.person.gender; }
|
get() { return this.person.gender; }
|
||||||
},
|
},
|
||||||
|
civility: {
|
||||||
|
set(value) { this.person.civility = {id: value, type: 'chill_main_civility'}; },
|
||||||
|
get() { return this.person.civility ? this.person.civility.id : null; }
|
||||||
|
},
|
||||||
birthDate: {
|
birthDate: {
|
||||||
set(value) {
|
set(value) {
|
||||||
if (this.person.birthdate) {
|
if (this.person.birthdate) {
|
||||||
@ -195,6 +250,10 @@ export default {
|
|||||||
set(value) { this.person.email = value; },
|
set(value) { this.person.email = value; },
|
||||||
get() { return this.person.email; }
|
get() { return this.person.email; }
|
||||||
},
|
},
|
||||||
|
showAddressForm: {
|
||||||
|
set(value) { this.showAddressFormValue = value; },
|
||||||
|
get() { return this.showAddressFormValue; }
|
||||||
|
},
|
||||||
genderClass() {
|
genderClass() {
|
||||||
switch (this.person.gender) {
|
switch (this.person.gender) {
|
||||||
case 'woman':
|
case 'woman':
|
||||||
@ -230,6 +289,13 @@ export default {
|
|||||||
.then(altNames => {
|
.then(altNames => {
|
||||||
this.config.altNames = altNames;
|
this.config.altNames = altNames;
|
||||||
});
|
});
|
||||||
|
getCivilities()
|
||||||
|
.then(civilities => {
|
||||||
|
if ('results' in civilities) {
|
||||||
|
this.config.civilities = civilities.results;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (this.action !== 'create') {
|
if (this.action !== 'create') {
|
||||||
this.loadData();
|
this.loadData();
|
||||||
}
|
}
|
||||||
@ -273,6 +339,9 @@ export default {
|
|||||||
this.person.firstName = queryItem;
|
this.person.firstName = queryItem;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
submitNewAddress(payload) {
|
||||||
|
this.person.addressId = payload.addressId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -293,4 +362,9 @@ dl {
|
|||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
div.form-check {
|
||||||
|
label {
|
||||||
|
margin-left: 0.5em!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -38,6 +38,15 @@ const personMessages = {
|
|||||||
man: "Masculin",
|
man: "Masculin",
|
||||||
neuter: "Neutre, non binaire",
|
neuter: "Neutre, non binaire",
|
||||||
undefined: "Non renseigné"
|
undefined: "Non renseigné"
|
||||||
|
},
|
||||||
|
civility: {
|
||||||
|
title: "Civilité",
|
||||||
|
placeholder: "Choisissez la civilité",
|
||||||
|
},
|
||||||
|
address: {
|
||||||
|
create_address: "Ajouter une adresse",
|
||||||
|
show_address_form: "Créer un ménage et ajouter une adresse",
|
||||||
|
warning: "Un nouveau ménage va être créé. L'usager sera membre de ce ménage."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error_only_one_person: "Une seule personne peut être sélectionnée !"
|
error_only_one_person: "Une seule personne peut être sélectionnée !"
|
||||||
|
@ -4,17 +4,19 @@
|
|||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
{{ encore_entry_script_tags('mod_set_referrer') }}
|
{{ encore_entry_script_tags('mod_set_referrer') }}
|
||||||
|
{{ encore_entry_script_tags('mod_pickentity_type') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
{{ encore_entry_link_tags('mod_set_referrer') }}
|
{{ encore_entry_link_tags('mod_set_referrer') }}
|
||||||
|
{{ encore_entry_link_tags('mod_pickentity_type') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% macro period_meta(period) %}
|
{% macro period_meta(period) %}
|
||||||
{% if is_granted('CHILL_PERSON_ACCOMPANYING_PERIOD_UPDATE', period) %}
|
{% if is_granted('CHILL_PERSON_ACCOMPANYING_PERIOD_UPDATE', period) %}
|
||||||
<div class="item-col item-meta">
|
<div class="item-col item-meta">
|
||||||
{% set job_id = null %}
|
{% set job_id = null %}
|
||||||
{% if period.job is defined %}
|
{% if period.job is defined and period.job is not null %}
|
||||||
{% set job_id = period.job.id %}
|
{% set job_id = period.job.id %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<span
|
<span
|
||||||
@ -28,9 +30,9 @@
|
|||||||
|
|
||||||
|
|
||||||
{% macro period_actions(period) %}
|
{% macro period_actions(period) %}
|
||||||
{% if is_granted('CHILL_PERSON_ACCOMPANYING_PERIOD_SEE', period) %}
|
{% if is_granted('CHILL_PERSON_ACCOMPANYING_PERIOD_UPDATE', period) %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ chill_path_add_return_path('chill_person_accompanying_course_index', {'accompanying_period_id': period.id}) }}" class="btn btn-show"></a>
|
<a href="{{ chill_path_add_return_path('chill_person_accompanying_course_edit', {'accompanying_period_id': period.id}) }}" class="btn btn-edit"></a>
|
||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
@ -38,45 +40,66 @@
|
|||||||
{% import _self as m %}
|
{% import _self as m %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="col-10">
|
<div class="row col-10">
|
||||||
<h1>{{ block('title') }}</h1>
|
<h1>{{ block('title') }}</h1>
|
||||||
|
|
||||||
{{ form_start(form) }}
|
|
||||||
<div class="row filter-box">
|
<div class="row filter-box">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
{{ form_start(form) }}
|
||||||
{{ form_label(form.user ) }}
|
{{ form_label(form.user ) }}
|
||||||
{{ form_widget(form.user, {'attr': {'class': 'select2'}}) }}
|
{{ form_widget(form.user, {'attr': {'class': 'select2'}}) }}
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul class="record_actions">
|
<ul class="record_actions">
|
||||||
<li>
|
<li>
|
||||||
<button type="submit" class="btn btn-save change-icon">
|
<button type="submit" class="btn btn-misc">
|
||||||
<i class="fa fa-filter"></i> Filtrer
|
<i class="fa fa-filter"></i> {{ 'Filter'|trans }}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{{ form_end(form) }}
|
{{ form_end(form) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
{% if form.user.vars.value is empty %}
|
<div class="col-md-6">
|
||||||
<p class="chill-no-data-statement">{{ 'period_by_user_list.Pick a user'|trans }}</p>
|
{% if userFrom is not null %}
|
||||||
{% elseif periods|length == 0 and form.user.vars.value is not empty %}
|
<div>
|
||||||
<p class="chill-no-data-statement">{{ 'period_by_user_list.Any course or no authorization to see them'|trans }}</p>
|
{{ form_start(assignForm) }}
|
||||||
|
{{ form_label(assignForm.userTo ) }}
|
||||||
|
{{ form_widget(assignForm.userTo, {'attr': {'class': 'select2'}}) }}
|
||||||
|
</div>
|
||||||
|
<ul class="record_actions">
|
||||||
|
<li>
|
||||||
|
<button type="submit" class="btn btn-update change-icon">
|
||||||
|
{{ 'reassign.Reassign'|trans }}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{{ form_end(assignForm) }}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
<div class="alert alert-info">{{ 'reassign.List periods to be able to reassign them'|trans }}</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if userFrom is not null %}
|
||||||
<p><span class="badge rounded-pill bg-primary">{{ paginator.totalItems }}</span> parcours à réassigner (calculé ce jour à {{ null|format_time('medium') }})</p>
|
<p><span class="badge rounded-pill bg-primary">{{ paginator.totalItems }}</span> parcours à réassigner (calculé ce jour à {{ null|format_time('medium') }})</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<div class="flex-table">
|
<div class="flex-table">
|
||||||
{% for period in periods %}
|
{% for period in periods %}
|
||||||
{% include '@ChillPerson/AccompanyingPeriod/_list_item.html.twig' with {'period': period,
|
{% include '@ChillPerson/AccompanyingPeriod/_list_item.html.twig' with {'period': period,
|
||||||
'recordAction': m.period_actions(period), 'itemMeta': m.period_meta(period) } %}
|
'recordAction': m.period_actions(period), 'itemMeta': m.period_meta(period) } %}
|
||||||
|
{% else %}
|
||||||
|
{% if userFrom is same as(null) %}
|
||||||
|
<p class="chill-no-data-statement">{{ 'period_by_user_list.Pick a user'|trans }}</p>
|
||||||
|
{% else %}
|
||||||
|
<p class="chill-no-data-statement">{{ 'period_by_user_list.Any course or no authorization to see them'|trans }}</p>
|
||||||
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
{% if paginator is defined %}
|
||||||
{{ chill_pagination(paginator) }}
|
{{ chill_pagination(paginator) }}
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
@ -93,6 +93,8 @@
|
|||||||
|
|
||||||
{{ form_row(form.gender, { 'label' : 'Gender'|trans }) }}
|
{{ form_row(form.gender, { 'label' : 'Gender'|trans }) }}
|
||||||
|
|
||||||
|
{{ form_row(form.civility, { 'label' : 'Civility'|trans }) }}
|
||||||
|
|
||||||
{{ form_row(form.birthdate, { 'label' : 'Date of birth'|trans }) }}
|
{{ form_row(form.birthdate, { 'label' : 'Date of birth'|trans }) }}
|
||||||
|
|
||||||
{{ form_row(form.phonenumber, { 'label' : 'Phonenumber'|trans }) }}
|
{{ form_row(form.phonenumber, { 'label' : 'Phonenumber'|trans }) }}
|
||||||
@ -105,6 +107,13 @@
|
|||||||
{{ form_row(form.center) }}
|
{{ form_row(form.center) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<div id=addressForm>
|
||||||
|
{{ form_row(form.addressForm) }}
|
||||||
|
</div>
|
||||||
|
<div id=address>
|
||||||
|
{{ form_row(form.address) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<ul class="record_actions sticky-form-buttons">
|
<ul class="record_actions sticky-form-buttons">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a class="btn btn-create dropdown-toggle"
|
<a class="btn btn-create dropdown-toggle"
|
||||||
@ -132,4 +141,10 @@
|
|||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
{{ encore_entry_script_tags('page_suggest_names') }}
|
{{ encore_entry_script_tags('page_suggest_names') }}
|
||||||
|
{{ encore_entry_script_tags('page_create_person') }}
|
||||||
|
{{ encore_entry_script_tags('mod_input_address') }}
|
||||||
{% endblock js %}
|
{% endblock js %}
|
||||||
|
|
||||||
|
{% block css %}
|
||||||
|
{{ encore_entry_link_tags('mod_input_address') }}
|
||||||
|
{% endblock %}
|
||||||
|
@ -48,7 +48,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="wl-col list">
|
<div class="wl-col list">
|
||||||
<p class="item">
|
<p class="item">
|
||||||
|
{% if p.position %}
|
||||||
{{ p.position.label|localize_translatable_string }}
|
{{ p.position.label|localize_translatable_string }}
|
||||||
|
{% endif %}
|
||||||
{% if p.holder %}
|
{% if p.holder %}
|
||||||
<span class="fa-stack fa-holder" title="{{ 'houshold.holder'|trans|e('html_attr') }}">
|
<span class="fa-stack fa-holder" title="{{ 'houshold.holder'|trans|e('html_attr') }}">
|
||||||
<i class="fa fa-circle fa-stack-1x text-success"></i>
|
<i class="fa fa-circle fa-stack-1x text-success"></i>
|
||||||
|
@ -25,6 +25,9 @@ use function in_array;
|
|||||||
|
|
||||||
class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
|
class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRoleHierarchyInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* all the roles that are linked to an accompanying period.
|
||||||
|
*/
|
||||||
public const ALL = [
|
public const ALL = [
|
||||||
self::SEE,
|
self::SEE,
|
||||||
self::SEE_DETAILS,
|
self::SEE_DETAILS,
|
||||||
@ -37,6 +40,11 @@ class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRoleH
|
|||||||
self::RE_OPEN_COURSE,
|
self::RE_OPEN_COURSE,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give the ability to see all confidential courses.
|
||||||
|
*/
|
||||||
|
public const CONFIDENTIAL_CRUD = 'CHILL_PERSON_ACCOMPANYING_PERIOD_CRUD_CONFIDENTIAL';
|
||||||
|
|
||||||
public const CREATE = 'CHILL_PERSON_ACCOMPANYING_PERIOD_CREATE';
|
public const CREATE = 'CHILL_PERSON_ACCOMPANYING_PERIOD_CREATE';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -66,6 +74,11 @@ class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRoleH
|
|||||||
*/
|
*/
|
||||||
public const RE_OPEN_COURSE = 'CHILL_PERSON_ACCOMPANYING_PERIOD_REOPEN';
|
public const RE_OPEN_COURSE = 'CHILL_PERSON_ACCOMPANYING_PERIOD_REOPEN';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow user to bulk reassign the courses.
|
||||||
|
*/
|
||||||
|
public const REASSIGN_BULK = 'CHILL_PERSON_ACCOMPANYING_COURSE_REASSIGN_BULK';
|
||||||
|
|
||||||
public const SEE = 'CHILL_PERSON_ACCOMPANYING_PERIOD_SEE';
|
public const SEE = 'CHILL_PERSON_ACCOMPANYING_PERIOD_SEE';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,7 +111,7 @@ class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRoleH
|
|||||||
$this->security = $security;
|
$this->security = $security;
|
||||||
$this->voterHelper = $voterHelperFactory
|
$this->voterHelper = $voterHelperFactory
|
||||||
->generate(self::class)
|
->generate(self::class)
|
||||||
->addCheckFor(null, [self::CREATE])
|
->addCheckFor(null, [self::CREATE, self::REASSIGN_BULK])
|
||||||
->addCheckFor(AccompanyingPeriod::class, [self::TOGGLE_CONFIDENTIAL, ...self::ALL])
|
->addCheckFor(AccompanyingPeriod::class, [self::TOGGLE_CONFIDENTIAL, ...self::ALL])
|
||||||
->addCheckFor(Person::class, [self::SEE])
|
->addCheckFor(Person::class, [self::SEE])
|
||||||
->build();
|
->build();
|
||||||
@ -106,7 +119,17 @@ class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRoleH
|
|||||||
|
|
||||||
public function getRoles(): array
|
public function getRoles(): array
|
||||||
{
|
{
|
||||||
return self::ALL;
|
return [
|
||||||
|
self::SEE,
|
||||||
|
self::SEE_DETAILS,
|
||||||
|
self::CONFIDENTIAL_CRUD,
|
||||||
|
self::CREATE,
|
||||||
|
self::EDIT,
|
||||||
|
self::DELETE,
|
||||||
|
self::FULL,
|
||||||
|
self::TOGGLE_CONFIDENTIAL_ALL,
|
||||||
|
self::REASSIGN_BULK,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRolesWithHierarchy(): array
|
public function getRolesWithHierarchy(): array
|
||||||
@ -116,7 +139,7 @@ class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRoleH
|
|||||||
|
|
||||||
public function getRolesWithoutScope(): array
|
public function getRolesWithoutScope(): array
|
||||||
{
|
{
|
||||||
return [];
|
return [self::REASSIGN_BULK];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function supports($attribute, $subject)
|
protected function supports($attribute, $subject)
|
||||||
@ -166,8 +189,11 @@ class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRoleH
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->voterHelper->voteOnAttribute(self::TOGGLE_CONFIDENTIAL_ALL, $subject, $token)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
// return $this->voterHelper->voteOnAttribute(self::TOGGLE_CONFIDENTIAL_ALL, $subject, $token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self::TOGGLE_INTENSITY === $attribute) {
|
if (self::TOGGLE_INTENSITY === $attribute) {
|
||||||
@ -180,6 +206,10 @@ class AccompanyingPeriodVoter extends AbstractChillVoter implements ProvideRoleH
|
|||||||
|
|
||||||
// if confidential, only the referent can see it
|
// if confidential, only the referent can see it
|
||||||
if ($subject->isConfidential()) {
|
if ($subject->isConfidential()) {
|
||||||
|
if ($this->voterHelper->voteOnAttribute(self::CONFIDENTIAL_CRUD, $subject, $token)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return $token->getUser() === $subject->getUser();
|
return $token->getUser() === $subject->getUser();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,12 +116,18 @@ class MembersEditorNormalizer implements DenormalizerAwareInterface, Denormalize
|
|||||||
$format,
|
$format,
|
||||||
$context
|
$context
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (array_key_exists('position', $concerned)) {
|
||||||
$position = $this->denormalizer->denormalize(
|
$position = $this->denormalizer->denormalize(
|
||||||
$concerned['position'] ?? null,
|
$concerned['position'] ?? null,
|
||||||
Position::class,
|
Position::class,
|
||||||
$format,
|
$format,
|
||||||
$context
|
$context
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
$position = null;
|
||||||
|
}
|
||||||
|
|
||||||
$startDate = $this->denormalizer->denormalize(
|
$startDate = $this->denormalizer->denormalize(
|
||||||
$concerned['start_date'] ?? null,
|
$concerned['start_date'] ?? null,
|
||||||
DateTimeImmutable::class,
|
DateTimeImmutable::class,
|
||||||
|
@ -12,6 +12,7 @@ declare(strict_types=1);
|
|||||||
namespace Chill\PersonBundle\Serializer\Normalizer;
|
namespace Chill\PersonBundle\Serializer\Normalizer;
|
||||||
|
|
||||||
use Chill\MainBundle\Entity\Center;
|
use Chill\MainBundle\Entity\Center;
|
||||||
|
use Chill\MainBundle\Entity\Civility;
|
||||||
use Chill\MainBundle\Phonenumber\PhoneNumberHelperInterface;
|
use Chill\MainBundle\Phonenumber\PhoneNumberHelperInterface;
|
||||||
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
|
use Chill\MainBundle\Security\Resolver\CenterResolverManagerInterface;
|
||||||
use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension;
|
use Chill\MainBundle\Templating\Entity\ChillEntityRenderExtension;
|
||||||
@ -101,6 +102,7 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
|
|||||||
'center',
|
'center',
|
||||||
'altNames',
|
'altNames',
|
||||||
'email',
|
'email',
|
||||||
|
'civility',
|
||||||
];
|
];
|
||||||
|
|
||||||
$fields = array_filter(
|
$fields = array_filter(
|
||||||
@ -176,6 +178,13 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
|
|||||||
case 'email':
|
case 'email':
|
||||||
$person->setEmail($data[$item]);
|
$person->setEmail($data[$item]);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'civility':
|
||||||
|
$civility = $this->denormalizer->denormalize($data[$item], Civility::class, $format, []);
|
||||||
|
|
||||||
|
$person->setCivility($civility);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,6 +221,7 @@ class PersonJsonNormalizer implements DenormalizerAwareInterface, NormalizerAwar
|
|||||||
'mobilenumber' => $this->normalizer->normalize($person->getMobilenumber(), $format, $context),
|
'mobilenumber' => $this->normalizer->normalize($person->getMobilenumber(), $format, $context),
|
||||||
'email' => $person->getEmail(),
|
'email' => $person->getEmail(),
|
||||||
'gender' => $person->getGender(),
|
'gender' => $person->getGender(),
|
||||||
|
'civility' => $this->normalizer->normalize($person->getCivility(), $format, $context),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (in_array('minimal', $groups, true) && 1 === count($groups)) {
|
if (in_array('minimal', $groups, true) && 1 === count($groups)) {
|
||||||
|
@ -1137,7 +1137,7 @@ paths:
|
|||||||
200:
|
200:
|
||||||
description: "OK"
|
description: "OK"
|
||||||
400:
|
400:
|
||||||
description: "transition cannot be applyed"
|
description: "transition cannot be applied"
|
||||||
|
|
||||||
/1.0/person/accompanying-course/{id}/confidential.json:
|
/1.0/person/accompanying-course/{id}/confidential.json:
|
||||||
post:
|
post:
|
||||||
@ -1327,6 +1327,28 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: "ok"
|
description: "ok"
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- household
|
||||||
|
requestBody:
|
||||||
|
description: "A household"
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Household"
|
||||||
|
summary: Post a new household
|
||||||
|
responses:
|
||||||
|
401:
|
||||||
|
description: "Unauthorized"
|
||||||
|
404:
|
||||||
|
description: "Not found"
|
||||||
|
200:
|
||||||
|
description: "OK"
|
||||||
|
422:
|
||||||
|
description: "Unprocessable entity (validation errors)"
|
||||||
|
400:
|
||||||
|
description: "transition cannot be applied"
|
||||||
|
|
||||||
/1.0/person/household/{id}.json:
|
/1.0/person/household/{id}.json:
|
||||||
get:
|
get:
|
||||||
@ -1507,7 +1529,7 @@ paths:
|
|||||||
422:
|
422:
|
||||||
description: "Unprocessable entity (validation errors)"
|
description: "Unprocessable entity (validation errors)"
|
||||||
400:
|
400:
|
||||||
description: "transition cannot be applyed"
|
description: "transition cannot be applied"
|
||||||
|
|
||||||
/1.0/person/household/{id}/address.json:
|
/1.0/person/household/{id}/address.json:
|
||||||
post:
|
post:
|
||||||
@ -1543,7 +1565,7 @@ paths:
|
|||||||
422:
|
422:
|
||||||
description: "Unprocessable entity (validation errors)"
|
description: "Unprocessable entity (validation errors)"
|
||||||
400:
|
400:
|
||||||
description: "transition cannot be applyed"
|
description: "transition cannot be applied"
|
||||||
|
|
||||||
/1.0/person/social/social-action.json:
|
/1.0/person/social/social-action.json:
|
||||||
get:
|
get:
|
||||||
|
@ -22,4 +22,5 @@ module.exports = function(encore, entries)
|
|||||||
encore.addEntry('page_accompanying_course_index_masonry', __dirname + '/Resources/public/page/accompanying_course_index/masonry.js');
|
encore.addEntry('page_accompanying_course_index_masonry', __dirname + '/Resources/public/page/accompanying_course_index/masonry.js');
|
||||||
encore.addEntry('page_person_resource_showhide_input', __dirname + '/Resources/public/page/person_resource/showhide-input.js');
|
encore.addEntry('page_person_resource_showhide_input', __dirname + '/Resources/public/page/person_resource/showhide-input.js');
|
||||||
encore.addEntry('page_suggest_names', __dirname + '/Resources/public/page/person/suggest-names.js');
|
encore.addEntry('page_suggest_names', __dirname + '/Resources/public/page/person/suggest-names.js');
|
||||||
|
encore.addEntry('page_create_person', __dirname + '/Resources/public/page/person/create-person.js');
|
||||||
};
|
};
|
||||||
|
@ -86,6 +86,8 @@ Civility: Civilité
|
|||||||
choose civility: --
|
choose civility: --
|
||||||
All genders: tous les genres
|
All genders: tous les genres
|
||||||
Any person selected: Aucune personne sélectionnée
|
Any person selected: Aucune personne sélectionnée
|
||||||
|
Create a household and add an address: Créer un ménage et ajouter une adresse
|
||||||
|
A new household will be created. The person will be member of this household.: Un nouveau ménage va être créé. L'usager sera membre de ce ménage.
|
||||||
|
|
||||||
# dédoublonnage
|
# dédoublonnage
|
||||||
Old person: Doublon
|
Old person: Doublon
|
||||||
@ -301,7 +303,16 @@ CHILL_PERSON_CREATE: Ajouter des personnes
|
|||||||
CHILL_PERSON_STATS: Statistiques sur les personnes
|
CHILL_PERSON_STATS: Statistiques sur les personnes
|
||||||
CHILL_PERSON_LISTS: Liste des personnes
|
CHILL_PERSON_LISTS: Liste des personnes
|
||||||
CHILL_PERSON_DUPLICATE: Gérer les doublons de personnes
|
CHILL_PERSON_DUPLICATE: Gérer les doublons de personnes
|
||||||
CHILL_PERSON_ACCOMPANYING_PERIOD_SEE: Voir les périodes d'accompagnement
|
CHILL_PERSON_ACCOMPANYING_PERIOD_SEE: Vision simplifiée d'une période d'accompagnement
|
||||||
|
CHILL_PERSON_ACCOMPANYING_PERIOD_CONFIDENTIAL: Voir et modifier les périodes d'accompagnement confidentielles
|
||||||
|
CHILL_PERSON_ACCOMPANYING_PERIOD_DELETE: Supprimer une période d'accompagnement
|
||||||
|
CHILL_PERSON_ACCOMPANYING_PERIOD_RE_OPEN: Ré-ouvrir un parcours clotûré
|
||||||
|
CHILL_PERSON_ACCOMPANYING_PERIOD_TOGGLE_CONFIDENTIAL_ALL: Modifier la confidentialité de tous les parcours
|
||||||
|
CHILL_PERSON_ACCOMPANYING_PERIOD_CREATE: Créer une période d'accompagnement
|
||||||
|
CHILL_PERSON_ACCOMPANYING_PERIOD_UPDATE: Modifier une période d'accompagnement
|
||||||
|
CHILL_PERSON_ACCOMPANYING_PERIOD_FULL: Voir les détails, créer, supprimer et mettre à jour une période d'accompagnement
|
||||||
|
CHILL_PERSON_ACCOMPANYING_COURSE_REASSIGN_BULK: Réassigner les parcours en lot
|
||||||
|
CHILL_PERSON_ACCOMPANYING_PERIOD_SEE_DETAILS: Voir les détails d'une période d'accompagnement
|
||||||
|
|
||||||
#period
|
#period
|
||||||
Period closed!: Période clôturée!
|
Period closed!: Période clôturée!
|
||||||
@ -661,3 +672,12 @@ period_by_user_list:
|
|||||||
Period by user: Parcours d'accompagnement par utilisateur
|
Period by user: Parcours d'accompagnement par utilisateur
|
||||||
Pick a user: Choisissez un utilisateur pour obtenir la liste de ses parcours
|
Pick a user: Choisissez un utilisateur pour obtenir la liste de ses parcours
|
||||||
Any course or no authorization to see them: Aucun parcours pour ce référent, ou aucun droit pour visualiser les parcours de ce référent.
|
Any course or no authorization to see them: Aucun parcours pour ce référent, ou aucun droit pour visualiser les parcours de ce référent.
|
||||||
|
|
||||||
|
reassign:
|
||||||
|
Bulk reassign: Réassigner les parcours
|
||||||
|
Current user: Parcours par référent
|
||||||
|
Next user: Nouveau référent
|
||||||
|
Choose a user and click on "Filter" to apply: Choisissez un utilisateur et cliquez sur "Filtrer" pour visualiser ses parcours
|
||||||
|
All periods on this list will be reassigned to this user, excepted the one you manually reassigned before: Tous les parcours visibles sur cette page seront assignés à cet utilisateur, sauf ceux que vous aurez assigné à un utilisateur manuellement.
|
||||||
|
Reassign: Assigner le référent
|
||||||
|
List periods to be able to reassign them: Choisissez un utilisateur et cliquez sur "Filtrer" pour visualiser ses parcours. Vous pourrez ensuite les réassigner.
|
||||||
|
@ -66,3 +66,6 @@ The person where the course is located must be associated to the course. Change
|
|||||||
#relationship
|
#relationship
|
||||||
relationship:
|
relationship:
|
||||||
duplicate: Une relation de filiation existe déjà entre ces 2 personnes
|
duplicate: Une relation de filiation existe déjà entre ces 2 personnes
|
||||||
|
|
||||||
|
person_creation:
|
||||||
|
If you want to create an household, an address is required: Pour la création d'un ménage, une adresse est requise
|
||||||
|
@ -99,8 +99,6 @@ final class TaskVoter extends AbstractChillVoter implements ProvideRoleHierarchy
|
|||||||
|
|
||||||
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
|
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
|
||||||
{
|
{
|
||||||
$this->logger->debug(sprintf('Voting from %s class', self::class));
|
|
||||||
|
|
||||||
if (!$token->getUser() instanceof User) {
|
if (!$token->getUser() instanceof User) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user