Merge branch 'master' into upgrade-php82

This commit is contained in:
2023-03-28 11:11:51 +02:00
30 changed files with 419 additions and 139 deletions

View File

@@ -160,6 +160,14 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
*/
private ?DateInterval $warningInterval = null;
/**
* @ORM\Column(type="integer", nullable=true)
* @Serializer\Groups({"read", "docgen:read"})
* @Serializer\Groups({"write"})
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
*/
private ?int $timeSpent = null;
public function __construct()
{
$this->documents = new ArrayCollection();
@@ -265,6 +273,11 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
return $this->warningInterval;
}
public function getTimeSpent(): ?int
{
return $this->timeSpent;
}
public function removeDocument(AccompanyingPeriodWorkEvaluationDocument $document): self
{
$this->documents->removeElement($document);
@@ -322,6 +335,13 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
return $this;
}
public function setTimeSpent(?int $timeSpent): self
{
$this->timeSpent = $timeSpent;
return $this;
}
public function setEvaluation(?Evaluation $evaluation): AccompanyingPeriodWorkEvaluation
{
if (

View File

@@ -47,6 +47,7 @@ class ListEvaluation implements ListInterface, GroupedExportInterface
'endDate',
'maxDate',
'warningInterval',
'timeSpent',
'acpw_id',
'acpw_startDate',
'acpw_endDate',
@@ -295,6 +296,9 @@ class ListEvaluation implements ListInterface, GroupedExportInterface
$qb->addSelect(sprintf('workeval.%s AS %s', $field, $field));
}
// add the time spent field
$qb->addSelect('(workeval.timeSpent / 60) AS timeSpent');
// those with identity
foreach (['createdBy', 'updatedBy'] as $field) {
$qb->addSelect(sprintf('IDENTITY(workeval.%s) AS %s', $field, $field));

View File

@@ -19,7 +19,6 @@ use Chill\PersonBundle\Entity\SocialWork\SocialAction;
use Chill\PersonBundle\Export\Declarations;
use Chill\PersonBundle\Templating\Entity\SocialActionRender;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Query\Expr\Andx;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
@@ -52,45 +51,39 @@ class SocialWorkTypeFilter implements FilterInterface
public function alterQuery(QueryBuilder $qb, $data)
{
$where = $qb->getDQLPart('where');
if (count($data['actionType']) > 0) {
$clause = $qb->expr()->in('acpw.socialAction', ':actionType');
if ($where instanceof Andx) {
$where->add($clause);
} else {
$where = $qb->expr()->andX($clause);
}
$qb->setParameter('actionType', $data['actionType']);
$qb
->andWhere($qb->expr()->in('acpw.socialAction', ':actionType'))
->setParameter('actionType', $data['actionType']);
}
if (count($data['goal']) > 0) {
if (!in_array('goal', $qb->getAllAliases(), true)) {
$qb->join('acpw.goals', 'goal');
if (!in_array('acpw_goal', $qb->getAllAliases(), true)) {
$qb->join('acpw.goals', 'acpw_goal');
}
$where->add(
$qb->expr()->in('goal.id', ':goals')
);
$orX = $qb->expr()->orX();
foreach ($data['goal'] as $goal) {
$qb->setParameter('goals', $data['goal']);
}
/** @var Goal $goal */
$andX = $qb->expr()->andX();
$andX->add($qb->expr()->eq('acpw_goal.goal', $goalId = ':goal_'.uniqid()));
$qb->setParameter($goalId, $goal);
if (count($data['result']) > 0) {
if (!in_array('result', $qb->getAllAliases(), true)) {
$qb->join('acpw.results', 'result');
if (count($data['result']) > 0) {
$orXResult = $qb->expr()->orX();
foreach ($data['result'] as $result) {
/** @var Result $result */
$orXResult->add($qb->expr()->isMemberOf($resultId = ':result_'.uniqid(), 'acpw_goal.results'));
$qb->setParameter($resultId, $result);
}
$andX->add($orXResult);
}
$orX->add($andX);
}
$where->add(
$qb->expr()->in('result.id', ':results')
);
$qb->setParameter('results', $data['result']);
$qb->andWhere($orX);
}
$qb->add('where', $where);
}
public function applyOn(): string

View File

@@ -18,21 +18,25 @@ use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\SerializerInterface;
/**
* Pick user dymically, using vuejs module "AddPerson".
* m* Pick user dymically, using vuejs module "AddPerson".
*/
class PickPersonDynamicType extends AbstractType
{
private DenormalizerInterface $denormalizer;
private DenormalizerInterface $normalizer;
private SerializerInterface $serializer;
public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer)
public function __construct(DenormalizerInterface $denormalizer, SerializerInterface $serializer, NormalizerInterface $normalizer)
{
$this->denormalizer = $denormalizer;
$this->serializer = $serializer;
$this->normalizer = $normalizer;
}
public function buildForm(FormBuilderInterface $builder, array $options)
@@ -45,6 +49,11 @@ class PickPersonDynamicType extends AbstractType
$view->vars['multiple'] = $options['multiple'];
$view->vars['types'] = ['person'];
$view->vars['uniqid'] = uniqid('pick_user_dyn');
$view->vars['suggested'] = [];
foreach ($options['suggested'] as $person) {
$view->vars['suggested'][] = $this->normalizer->normalize($person, 'json', ['groups' => 'read']);
}
}
public function configureOptions(OptionsResolver $resolver)
@@ -52,7 +61,8 @@ class PickPersonDynamicType extends AbstractType
$resolver
->setDefault('multiple', false)
->setAllowedTypes('multiple', ['bool'])
->setDefault('compound', false);
->setDefault('compound', false)
->setDefault('suggested', []);
}
public function getBlockPrefix()

View File

@@ -49,6 +49,20 @@
</div>
</div>
<div class="row mb-3">
<label class="col-4 col-sm-2 col-md-4 col-lg-2 col-form-label">
{{ $t('evaluation_time_spent') }}
</label>
<div class="col-8 col-sm-4 col-md-8 col-lg-4">
<select class="form-control form-control-sm" type="time" v-model="timeSpent">
<option disabled value="">{{ $t('select_time_spent') }}</option>
<option v-for="time in timeSpentChoices" :value="time.value">
{{ time.text }}
</option>
</select>
</div>
</div>
<div class="row mb-3">
<label class="col-sm-4 col-form-label visually-hidden">{{ $t('evaluation_public_comment') }}</label>
<div class="col-sm-12">
@@ -191,6 +205,8 @@ const i18n = {
evaluation_choose_a_template: "Choisir un modèle",
evaluation_add_a_document: "Ajouter un document",
evaluation_add: "Ajouter une évaluation",
evaluation_time_spent: "Temps de rédaction",
select_time_spent: "Indiquez le temps de rédaction",
Documents: "Documents",
document_add: "Générer ou téléverser un document",
document_upload: "Téléverser un document",
@@ -224,6 +240,22 @@ export default {
maxPostSize: 15000000,
required: false,
},
timeSpentChoices: [
{ text: '1 minute', value: 60 }, { text: '2 minutes', value: 120 },
{ text: '3 minutes', value: 180 }, { text: '4 minutes', value: 240 },
{ text: '5 minutes', value: 300 }, { text: '10 minutes', value: 600 },
{ text: '15 minutes', value: 900 },{ text: '20 minutes', value: 1200 },
{ text: '25 minutes', value: 1500 }, { text: '30 minutes', value: 1800 },
{ text: '45 minutes', value: 2700 },{ text: '1 hour', value: 3600 },
{ text: '1 hour 15 minutes', value: 4500 }, { text: '1 hour 30 minutes', value: 5400 },
{ text: '1 hour 45 minutes', value: 6300 }, { text: '2 hours', value: 7200 },
{ text: '2 hours 30 minutes', value: 9000 }, { text: '3 hours', value: 10800 },
{ text: '3 hours 30 minutes', value: 12600 },{ text: '4 hours', value: 14400 },
{ text: '4 hours 30 minutes', value: 16200 },{ text: '5 hours', value: 18000 },
{ text: '5 hours 30 minutes', value: 19800 },{ text: '6 hours', value: 21600 },
{ text: '6 hours 30 minutes', value: 23400 },{ text: '7 hours', value: 25200 },
{ text: '7 hours 30 minutes', value: 27000 },{ text: '8 hours', value: 28800 },
]
}
},
computed: {
@@ -265,6 +297,10 @@ export default {
get() { return this.evaluation.warningInterval; },
set(v) { this.$store.commit('setEvaluationWarningInterval', { key: this.evaluation.key, days: v }); }
},
timeSpent: {
get() { return this.evaluation.timeSpent },
set(v) { this.$store.commit('setEvaluationTimeSpent', { key: this.evaluation.key, time: v}) }
},
comment: {
get() { return this.evaluation.comment; },
set(v) { this.$store.commit('setEvaluationComment', { key: this.evaluation.key, comment: v }); }

View File

@@ -116,6 +116,7 @@ const store = createStore({
endDate: e.endDate === null || e.endDate === '' ? null : { datetime: datetimeToISO(ISOToDate(e.endDate)) },
maxDate: e.maxDate === null || e.maxDate === '' ? null : { datetime: datetimeToISO(ISOToDate(e.maxDate)) },
warningInterval: intervalDaysToISO(e.warningInterval),
timeSpent: e.timeSpent,
comment: e.comment,
documents: e.documents
};
@@ -138,6 +139,7 @@ const store = createStore({
endDate: e.endDate !== null ? dateToISO(new Date(e.endDate.datetime)) : null,
maxDate: e.maxDate !== null ? dateToISO(new Date(e.maxDate.datetime)) : null,
warningInterval: e.warningInterval !== null ? intervalISOToDays(e.warningInterval) : null,
timeSpent: e.timeSpent !== null ? e.timeSpent : null,
documents: e.documents.map((d, docIndex) => {
return Object.assign(d, {
key: docIndex
@@ -258,6 +260,7 @@ const store = createStore({
endDate: null,
maxDate: null,
warningInterval: null,
timeSpent: null,
comment: "",
editEvaluation: true,
workflows_availables: state.work.workflows_availables_evaluation,
@@ -286,6 +289,10 @@ const store = createStore({
state.evaluationsPicked.find(e => e.key === key)
.warningInterval = days;
},
setEvaluationTimeSpent(state, {key, time}) {
state.evaluationsPicked.find(e => e.key === key)
.timeSpent = time;
},
setEvaluationComment(state, {key, comment}) {
state.evaluationsPicked.find(e => e.key === key)
.comment = comment;
@@ -482,7 +489,7 @@ const store = createStore({
;
commit('setIsPosting', true);
console.log('payload', payload);
console.log('the social action', payload);
return makeFetch('PUT', url, payload)
.then(data => {

View File

@@ -118,6 +118,18 @@
</li>
{% endif %}
{% endif %}
{% if e.timeSpent is not null and e.timeSpent > 0 %}
<li>
{% set minutes = (e.timeSpent / 60) %}
<span class="item-key">{{ 'accompanying_course_work.timeSpent'|trans ~ ' : ' }}</span> {{ 'duration.minute'|trans({ '{m}' : minutes }) }}
</li>
{% elseif displayContent is defined and displayContent == 'long' %}
<li>
<span class="item-key">{{ 'accompanying_course_work.timeSpent'|trans ~ ' : ' }}</span>
<span class="chill-no-data-statement">{{ 'Not given'|trans }}</span>
</li>
{% endif %}
</ul>
</li>
</ul>
@@ -143,7 +155,7 @@
{% else %}
<span class="chill-no-data-statement">{{ 'No document found'|trans }}</span>
{% endif %}
{% endif %}
</td>

View File

@@ -97,6 +97,21 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW
return AccompanyingPeriodWorkEvaluationDocumentVoter::SEE;
}
public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array
{
$suggestedUsers = $entityWorkflow->getUsersInvolved();
$referrer = $this->getRelatedEntity($entityWorkflow)
->getAccompanyingPeriodWorkEvaluation()
->getAccompanyingPeriodWork()
->getAccompanyingPeriod()
->getUser();
$suggestedUsers[spl_object_hash($referrer)] = $referrer;
return $suggestedUsers;
}
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string
{
return '@ChillPerson/Workflow/_evaluation_document.html.twig';

View File

@@ -87,6 +87,20 @@ class AccompanyingPeriodWorkEvaluationWorkflowHandler implements EntityWorkflowH
return AccompanyingPeriodWorkEvaluationVoter::SEE;
}
public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array
{
$suggestedUsers = $entityWorkflow->getUsersInvolved();
$referrer = $this->getRelatedEntity($entityWorkflow)
->getAccompanyingPeriodWork()
->getAccompanyingPeriod()
->getUser();
$suggestedUsers[spl_object_hash($referrer)] = $referrer;
return $suggestedUsers;
}
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string
{
return '@ChillPerson/Workflow/_evaluation.html.twig';

View File

@@ -94,6 +94,19 @@ class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHandlerInte
return null;
}
public function getSuggestedUsers(EntityWorkflow $entityWorkflow): array
{
$suggestedUsers = $entityWorkflow->getUsersInvolved();
$referrer = $this->getRelatedEntity($entityWorkflow)
->getAccompanyingPeriod()
->getUser();
$suggestedUsers[spl_object_hash($referrer)] = $referrer;
return $suggestedUsers;
}
public function getTemplate(EntityWorkflow $entityWorkflow, array $options = []): string
{
return '@ChillPerson/Workflow/_accompanying_period_work.html.twig';

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
final class Version20230210104424 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add a duration field to accompanyingPeriodWorkEvaluation';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation ADD timeSpent INT DEFAULT NULL');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation DROP timeSpent');
}
}

View File

@@ -908,6 +908,7 @@ accompanying_course_work:
remove: Supprimer une action d'accompagnement
social_evaluation: Évaluation
private_comment: Commentaire privé
timeSpent: Temps de rédaction
#
@@ -1139,6 +1140,7 @@ export:
updatedAt: Date de modification
createdBy: Créé par
updatedBy: Modifié par
timeSpent: Temps de rédaction (minutes)
acpw:
List of accompanying period works: Liste des actions
List description: Génère une liste des actions d'accompagnement, filtrée sur différents paramètres.