mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Fixes
This commit is contained in:
parent
0581b59dbd
commit
7e2bf91e09
@ -63,4 +63,28 @@ class PrivateCommentEmbeddable
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges comments from the provided object into the current object.
|
||||||
|
*
|
||||||
|
* Identifies common user IDs between the current object's comments and the
|
||||||
|
* newComment's comments. If a user ID exists in both, their comments are
|
||||||
|
* concatenated with the provided separator. If a user ID exists only in the
|
||||||
|
* newComment, their comment is added to the current object directly.
|
||||||
|
*
|
||||||
|
* @param self $commentsToAppend the object containing the new comments to be merged
|
||||||
|
* @param string $separator the string used to separate concatenated comments
|
||||||
|
*/
|
||||||
|
public function concatenateComments(self $commentsToAppend, string $separator = "\n\n-----------\n\n"): void
|
||||||
|
{
|
||||||
|
$commonUserIds = array_intersect(array_keys($this->comments), array_keys($commentsToAppend->getComments()));
|
||||||
|
|
||||||
|
foreach ($commentsToAppend->getComments() as $userId => $comment) {
|
||||||
|
if (in_array($userId, $commonUserIds, true)) {
|
||||||
|
$this->comments[$userId] = $this->comments[$userId].$separator.$commentsToAppend->getComments()[$userId];
|
||||||
|
} else {
|
||||||
|
$this->comments[$userId] = $commentsToAppend->getComments()[$userId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,9 @@ export interface ConflictHttpExceptionInterface
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic api method that can be adapted to any fetch request
|
* Generic api method that can be adapted to any fetch request
|
||||||
|
*
|
||||||
|
* This method is suitable make a single fetch. When performing a GET to fetch a list of elements, always consider pagination
|
||||||
|
* and use of the @link{fetchResults} method.
|
||||||
*/
|
*/
|
||||||
export const makeFetch = <Input, Output>(
|
export const makeFetch = <Input, Output>(
|
||||||
method: "POST" | "GET" | "PUT" | "PATCH" | "DELETE",
|
method: "POST" | "GET" | "PUT" | "PATCH" | "DELETE",
|
||||||
|
@ -282,9 +282,9 @@
|
|||||||
|
|
||||||
{% block pick_linked_entities_widget %}
|
{% block pick_linked_entities_widget %}
|
||||||
<input type="hidden" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value|escape('html_attr') }}" {% endif %} data-input-uniqid="{{ form.vars['uniqid'] }}" />
|
<input type="hidden" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value|escape('html_attr') }}" {% endif %} data-input-uniqid="{{ form.vars['uniqid'] }}" />
|
||||||
<div data-module="pick-linked-entities"
|
<div data-input-uniqid="{{ form.vars['uniqid'] }}" data-module="pick-linked-entities" data-pick-entities-type="{{ form.vars['pick-entities-type'] }}"
|
||||||
data-suggested="{{ form.vars['suggested']|json_encode|escape('html_attr') }}"
|
|
||||||
></div>
|
></div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block pick_postal_code_widget %}
|
{% block pick_postal_code_widget %}
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\MainBundle\Tests\Entity\Workflow;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\Embeddable\PrivateCommentEmbeddable;
|
||||||
|
use Chill\MainBundle\Entity\User;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class PrivateCommentEmbeddableTest extends TestCase
|
||||||
|
{
|
||||||
|
use ProphecyTrait;
|
||||||
|
|
||||||
|
public function testConcatenateComment(): void
|
||||||
|
{
|
||||||
|
$userA = $this->prophesize(User::class);
|
||||||
|
$userA->getId()->willReturn(1);
|
||||||
|
$userB = $this->prophesize(User::class);
|
||||||
|
$userB->getId()->willReturn(2);
|
||||||
|
$userC = $this->prophesize(User::class);
|
||||||
|
$userC->getId()->willReturn(3);
|
||||||
|
|
||||||
|
$toKeep = new PrivateCommentEmbeddable();
|
||||||
|
$toKeep->setCommentForUser($userA->reveal(), 'My comment for A');
|
||||||
|
$toKeep->setCommentForUser($userB->reveal(), 'My comment for B');
|
||||||
|
|
||||||
|
$toDelete = new PrivateCommentEmbeddable();
|
||||||
|
$toDelete->setCommentForUser($userC->reveal(), 'My comment for C');
|
||||||
|
$toDelete->setCommentForUser($userB->reveal(), 'Another comment for B');
|
||||||
|
|
||||||
|
$toKeep->concatenateComments($toDelete, '----');
|
||||||
|
|
||||||
|
self::assertTrue($toKeep->hasCommentForUser($userA->reveal()));
|
||||||
|
self::assertEquals('My comment for A', $toKeep->getCommentForUser($userA->reveal()));
|
||||||
|
|
||||||
|
self::assertTrue($toKeep->hasCommentForUser($userB->reveal()));
|
||||||
|
self::assertEquals('My comment for B----Another comment for B', $toKeep->getCommentForUser($userB->reveal()));
|
||||||
|
|
||||||
|
self::assertTrue($toKeep->hasCommentForUser($userC->reveal()));
|
||||||
|
self::assertEquals('My comment for C', $toKeep->getCommentForUser($userC->reveal()));
|
||||||
|
}
|
||||||
|
}
|
@ -314,7 +314,6 @@ final class AccompanyingCourseApiController extends ApiController
|
|||||||
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $accompanyingPeriod);
|
$this->denyAccessUnlessGranted(AccompanyingPeriodVoter::SEE, $accompanyingPeriod);
|
||||||
|
|
||||||
$works = $this->accompanyingPeriodWorkRepository->findBy(['accompanyingPeriod' => $accompanyingPeriod]);
|
$works = $this->accompanyingPeriodWorkRepository->findBy(['accompanyingPeriod' => $accompanyingPeriod]);
|
||||||
dump($works);
|
|
||||||
|
|
||||||
return $this->json($works, Response::HTTP_OK, [], ['groups' => ['read']]);
|
return $this->json($works, Response::HTTP_OK, [], ['groups' => ['read']]);
|
||||||
}
|
}
|
||||||
|
@ -218,14 +218,6 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
|
|||||||
|
|
||||||
public function setAccompanyingPeriodWork(?AccompanyingPeriodWork $accompanyingPeriodWork): AccompanyingPeriodWorkEvaluation
|
public function setAccompanyingPeriodWork(?AccompanyingPeriodWork $accompanyingPeriodWork): AccompanyingPeriodWorkEvaluation
|
||||||
{
|
{
|
||||||
if (
|
|
||||||
$accompanyingPeriodWork instanceof AccompanyingPeriodWork
|
|
||||||
&& $this->accompanyingPeriodWork instanceof AccompanyingPeriodWork
|
|
||||||
&& $this->accompanyingPeriodWork->getId() !== $accompanyingPeriodWork->getId()
|
|
||||||
) {
|
|
||||||
throw new \RuntimeException('Changing the accompanyingPeriodWork is not allowed');
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->accompanyingPeriodWork = $accompanyingPeriodWork;
|
$this->accompanyingPeriodWork = $accompanyingPeriodWork;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -24,8 +24,9 @@ class FindAccompanyingPeriodWorkType extends AbstractType
|
|||||||
{
|
{
|
||||||
$builder
|
$builder
|
||||||
->add('acpw', PickLinkedAccompanyingPeriodWorkType::class, [
|
->add('acpw', PickLinkedAccompanyingPeriodWorkType::class, [
|
||||||
'label' => 'Accompanying period work',
|
'label' => 'Social action',
|
||||||
'multiple' => false,
|
'multiple' => false,
|
||||||
|
'accompanyingPeriod' => $options['accompanyingPeriod'],
|
||||||
])
|
])
|
||||||
->add('direction', HiddenType::class, [
|
->add('direction', HiddenType::class, [
|
||||||
'data' => 'starting',
|
'data' => 'starting',
|
||||||
|
@ -11,6 +11,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Chill\PersonBundle\Form\Type;
|
namespace Chill\PersonBundle\Form\Type;
|
||||||
|
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
use Symfony\Component\Form\FormInterface;
|
use Symfony\Component\Form\FormInterface;
|
||||||
use Symfony\Component\Form\FormView;
|
use Symfony\Component\Form\FormView;
|
||||||
@ -19,29 +20,25 @@ use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
|||||||
|
|
||||||
class PickLinkedAccompanyingPeriodWorkType extends AbstractType
|
class PickLinkedAccompanyingPeriodWorkType extends AbstractType
|
||||||
{
|
{
|
||||||
public function __construct(private readonly NormalizerInterface $normalizer) {}
|
|
||||||
|
|
||||||
public function buildView(FormView $view, FormInterface $form, array $options)
|
public function buildView(FormView $view, FormInterface $form, array $options)
|
||||||
{
|
{
|
||||||
$view->vars['multiple'] = $options['multiple'];
|
$view->vars['multiple'] = $options['multiple'];
|
||||||
$view->vars['types'] = ['acpw'];
|
$view->vars['types'] = ['acpw'];
|
||||||
$view->vars['uniqid'] = uniqid('pick_acpw_dyn');
|
$view->vars['uniqid'] = uniqid('pick_acpw_dyn');
|
||||||
$view->vars['suggested'] = [];
|
|
||||||
$view->vars['as_id'] = true === $options['as_id'] ? '1' : '0';
|
$view->vars['as_id'] = true === $options['as_id'] ? '1' : '0';
|
||||||
$view->vars['submit_on_adding_new_entity'] = false;
|
$view->vars['submit_on_adding_new_entity'] = false;
|
||||||
|
$view->vars['pick-entities-type'] = 'acpw';
|
||||||
foreach ($options['suggested'] as $suggestion) {
|
$view->vars['attr']['data-accompanying-period-id'] = $options['accompanyingPeriod']->getId();
|
||||||
$view->vars['suggested'][] = $this->normalizer->normalize($suggestion, 'json', ['groups' => 'read']);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function configureOptions(OptionsResolver $resolver)
|
public function configureOptions(OptionsResolver $resolver)
|
||||||
{
|
{
|
||||||
$resolver
|
$resolver
|
||||||
|
->setRequired('accompanyingPeriod')
|
||||||
|
->setAllowedTypes('accompanyingPeriod', [AccompanyingPeriod::class])
|
||||||
->setDefault('multiple', false)
|
->setDefault('multiple', false)
|
||||||
->setAllowedTypes('multiple', ['bool'])
|
->setAllowedTypes('multiple', ['bool'])
|
||||||
->setDefault('compound', false)
|
->setDefault('compound', false)
|
||||||
->setDefault('suggested', [])
|
|
||||||
->setDefault('as_id', false)
|
->setDefault('as_id', false)
|
||||||
->setAllowedTypes('as_id', ['bool'])
|
->setAllowedTypes('as_id', ['bool'])
|
||||||
->setDefault('submit_on_adding_new_entity', false)
|
->setDefault('submit_on_adding_new_entity', false)
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import { createApp } from "vue";
|
|
||||||
import AccompanyingPeriodWorkSelectorModal from "../../vuejs/_components/AccompanyingPeriodWorkSelector/AccompanyingPeriodWorkSelectorModal.vue";
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
const el = document.getElementById("linked-acpw-selector");
|
|
||||||
if (el) {
|
|
||||||
const accompanyingPeriodId = el.dataset.accompanyingPeriod;
|
|
||||||
createApp(AccompanyingPeriodWorkSelectorModal, {
|
|
||||||
accompanyingPeriodId,
|
|
||||||
}).mount(el);
|
|
||||||
}
|
|
||||||
});
|
|
@ -0,0 +1,47 @@
|
|||||||
|
import { createApp } from "vue";
|
||||||
|
import AccompanyingPeriodWorkSelectorModal from "../../vuejs/_components/AccompanyingPeriodWorkSelector/AccompanyingPeriodWorkSelectorModal.vue";
|
||||||
|
import {AccompanyingPeriodWork} from "../../types";
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const elements = document.querySelectorAll<HTMLDivElement>('div[data-pick-entities-type="acpw"]');
|
||||||
|
elements.forEach(el => {
|
||||||
|
const uniqid = el.dataset.inputUniqid;
|
||||||
|
|
||||||
|
if (undefined === uniqid) {
|
||||||
|
throw 'Uniqid not found on this element';
|
||||||
|
}
|
||||||
|
|
||||||
|
const input = document.querySelector<HTMLInputElement>(`input[data-input-uniqid="${uniqid}"]`);
|
||||||
|
|
||||||
|
if (null === input) {
|
||||||
|
throw 'Element with uniqid not found: ' + uniqid;
|
||||||
|
}
|
||||||
|
|
||||||
|
const accompanyingPeriodIdAsString = input.dataset.accompanyingPeriodId;
|
||||||
|
|
||||||
|
if (undefined === accompanyingPeriodIdAsString) {
|
||||||
|
throw 'accompanying period id not found';
|
||||||
|
}
|
||||||
|
|
||||||
|
const accompanyingPeriodId = Number.parseInt(accompanyingPeriodIdAsString);
|
||||||
|
|
||||||
|
const app = createApp(
|
||||||
|
{
|
||||||
|
template:
|
||||||
|
'<accompanying-period-work-selector-modal :accompanying-period-id="accompanyingPeriodId" @pickWork="pickWork"></accompanying-period-work-selector-modal>',
|
||||||
|
components: {AccompanyingPeriodWorkSelectorModal},
|
||||||
|
data() {
|
||||||
|
return { accompanyingPeriodId };
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
pickWork: function(payload: {work: AccompanyingPeriodWork}) {
|
||||||
|
console.log("payload", payload);
|
||||||
|
input.value = payload.work.id.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
app.mount(el);
|
||||||
|
})
|
||||||
|
});
|
@ -84,7 +84,7 @@ export interface AccompanyingPeriodWorkEvaluationDocument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface AccompanyingPeriodWork {
|
export interface AccompanyingPeriodWork {
|
||||||
id?: number;
|
id: number;
|
||||||
accompanyingPeriod?: AccompanyingPeriod;
|
accompanyingPeriod?: AccompanyingPeriod;
|
||||||
accompanyingPeriodWorkEvaluations: AccompanyingPeriodWorkEvaluation[];
|
accompanyingPeriodWorkEvaluations: AccompanyingPeriodWorkEvaluation[];
|
||||||
createdAt?: string;
|
createdAt?: string;
|
||||||
|
@ -59,16 +59,22 @@ import {
|
|||||||
} from "translator";
|
} from "translator";
|
||||||
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
import { makeFetch } from "ChillMainAssets/lib/api/apiMethods";
|
||||||
|
|
||||||
|
type AccompanyingPeriodWorkSelectorModalProps = {
|
||||||
|
accompanyingPeriodId: number;
|
||||||
|
};
|
||||||
|
|
||||||
const selectedAcpw = ref<AccompanyingPeriodWork | null>(null);
|
const selectedAcpw = ref<AccompanyingPeriodWork | null>(null);
|
||||||
const showModal = ref(false);
|
const showModal = ref(false);
|
||||||
const accompanyingPeriodWorks = ref<AccompanyingPeriodWork[]>([]);
|
const accompanyingPeriodWorks = ref<AccompanyingPeriodWork[]>([]);
|
||||||
const props = defineProps({
|
const props = defineProps<AccompanyingPeriodWorkSelectorModalProps>();
|
||||||
accompanyingPeriodId: String,
|
|
||||||
});
|
const emit = defineEmits<{
|
||||||
|
pickWork: [payload: {work: AccompanyingPeriodWork|null}],
|
||||||
|
}>();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.accompanyingPeriodId) {
|
if (props.accompanyingPeriodId) {
|
||||||
getAccompanyingPeriodWorks(parseInt(props.accompanyingPeriodId));
|
getAccompanyingPeriodWorks(props.accompanyingPeriodId);
|
||||||
} else {
|
} else {
|
||||||
console.error("No accompanyingperiod id was given");
|
console.error("No accompanyingperiod id was given");
|
||||||
}
|
}
|
||||||
@ -85,19 +91,10 @@ const getAccompanyingPeriodWorks = (periodId: number) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(selectedAcpw, (newValue) => {
|
|
||||||
const inputField = document.getElementById(
|
|
||||||
"find_accompanying_period_work_acpw",
|
|
||||||
) as HTMLInputElement;
|
|
||||||
if (inputField) {
|
|
||||||
inputField.value = String(newValue?.id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const openModal = () => (showModal.value = true);
|
const openModal = () => (showModal.value = true);
|
||||||
const closeModal = () => (showModal.value = false);
|
const closeModal = () => (showModal.value = false);
|
||||||
const confirmSelection = () => {
|
const confirmSelection = () => {
|
||||||
selectedAcpw.value = selectedAcpw.value;
|
emit('pickWork', {work: selectedAcpw.value});
|
||||||
closeModal();
|
closeModal();
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{%- macro details(w, accompanyingCourse, options) -%}
|
{%- macro details(w, accompanyingCourse, options) -%}
|
||||||
{% include '@ChillPerson/AccompanyingCourseWork/_item.html.twig' with {
|
{% include '@ChillPerson/AccompanyingCourseWork/_item.html.twig' with {
|
||||||
'displayAction': true,
|
'displayAction': false,
|
||||||
'displayContent': 'short',
|
'displayContent': 'short',
|
||||||
'displayFontSmall': true,
|
'displayFontSmall': true,
|
||||||
'itemBlocClass': '',
|
'itemBlocClass': '',
|
||||||
'displayNotification': true
|
'displayNotification': false
|
||||||
} %}
|
} %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
@ -4,10 +4,21 @@
|
|||||||
|
|
||||||
{% block title %}{{ 'Assign an accompanying period work duplicate' }}{% endblock %}
|
{% block title %}{{ 'Assign an accompanying period work duplicate' }}{% endblock %}
|
||||||
|
|
||||||
|
{% import '@ChillPerson/AccompanyingPeriodWorkDuplicate/_details.html.twig' as details %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="person-duplicate">
|
<div class="person-duplicate">
|
||||||
|
|
||||||
<h1>{{ 'acpw_duplicate.Assign duplicate'|trans }}</h1>
|
<div class="col">
|
||||||
|
<h4>{{ 'acpw_duplicate.to keep'|trans ~ ':' }}</h4>
|
||||||
|
<div class="accompanying-course-work">
|
||||||
|
<div class="flex-table">
|
||||||
|
{{ details.details(acpw, accompanyingCourse) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>{{ 'acpw_duplicate.Assign duplicate'|trans }}</h3>
|
||||||
{{ form_start(form) }}
|
{{ form_start(form) }}
|
||||||
{%- if form.acpw is defined -%}
|
{%- if form.acpw is defined -%}
|
||||||
{{ form_row(form.acpw) }}
|
{{ form_row(form.acpw) }}
|
||||||
@ -22,7 +33,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button class="btn btn-save" type="submit">{{ 'Next'|trans }}</button>
|
<button class="btn btn-action" type="submit">{{ 'Next'|trans }}</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@ -32,9 +43,11 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
|
{{ parent() }}
|
||||||
{{ encore_entry_script_tags('mod_duplicate_selector') }}
|
{{ encore_entry_script_tags('mod_duplicate_selector') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block css %}
|
{% block css %}
|
||||||
|
{{ parent() }}
|
||||||
{{ encore_entry_link_tags('mod_duplicate_selector') }}
|
{{ encore_entry_link_tags('mod_duplicate_selector') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -50,7 +50,7 @@
|
|||||||
|
|
||||||
<ul class="col-12 record_actions">
|
<ul class="col-12 record_actions">
|
||||||
<li class="cancel">
|
<li class="cancel">
|
||||||
<a href="{{ path('chill_person_accompanying_period_work_assign_duplicate', {id : acpw.id}) }}" class="btn btn-chill-gray center margin-5">
|
<a href="{{ path('chill_person_accompanying_period_work_assign_duplicate', {id : acpw.id}) }}" class="btn btn-cancel">
|
||||||
{{ 'Return'|trans }}
|
{{ 'Return'|trans }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@ -62,7 +62,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<button class="btn btn-submit" type="submit"><i class="fa fa-cog fa-fw"></i>{{ 'Merge'|trans }}</button>
|
<button class="btn btn-submit" type="submit"><i class="bi bi-chevron-contract"></i>{{ 'Merge'|trans }}</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -12,202 +12,93 @@ declare(strict_types=1);
|
|||||||
namespace Chill\PersonBundle\Service\AccompanyingPeriodWork;
|
namespace Chill\PersonBundle\Service\AccompanyingPeriodWork;
|
||||||
|
|
||||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkReferrerHistory;
|
|
||||||
use Doctrine\DBAL\Exception;
|
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for merging two AccompanyingPeriodWork entities into a single entity.
|
||||||
|
*/
|
||||||
class AccompanyingPeriodWorkMergeService
|
class AccompanyingPeriodWorkMergeService
|
||||||
{
|
{
|
||||||
public function __construct(private readonly EntityManagerInterface $em) {}
|
public function __construct(private readonly EntityManagerInterface $em) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws Exception
|
* Merges two AccompanyingPeriodWork entities into one by transferring relevant data and removing the obsolete entity.
|
||||||
|
*
|
||||||
|
* @param AccompanyingPeriodWork $toKeep the entity to retain after the merge
|
||||||
|
* @param AccompanyingPeriodWork $toDelete the entity to be removed after transferring data
|
||||||
|
*
|
||||||
|
* @return AccompanyingPeriodWork the kept accompanying period work
|
||||||
*/
|
*/
|
||||||
public function merge(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete): void
|
public function merge(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete): AccompanyingPeriodWork
|
||||||
{
|
{
|
||||||
$conn = $this->em->getConnection();
|
$this->em->wrapInTransaction(function (EntityManagerInterface $entityManager) use ($toKeep, $toDelete) {
|
||||||
$conn->beginTransaction();
|
$this->alterStartDate($toKeep, $toDelete);
|
||||||
|
$this->alterEndDate($toKeep, $toDelete);
|
||||||
|
$this->concatenateComments($toKeep, $toDelete);
|
||||||
|
$this->transferWorkflowsSQL($toKeep, $toDelete);
|
||||||
|
$this->updateReferencesSQL($toKeep, $toDelete);
|
||||||
|
$entityManager->remove($toDelete);
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
return $toKeep;
|
||||||
$queries = array_merge(
|
|
||||||
$this->updateReferencesSQL($toKeep, $toDelete),
|
|
||||||
$this->transferWorkflowsSQL($toKeep, $toDelete),
|
|
||||||
$this->generateStartDateSQL($toDelete, $toKeep),
|
|
||||||
$this->generateEndDateSQL($toDelete, $toKeep),
|
|
||||||
$this->generateCommentSQL($toDelete, $toKeep),
|
|
||||||
$this->removeAccompanyingPeriodWork($toDelete)
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach ($queries as $query) {
|
|
||||||
dump($query);
|
|
||||||
$conn->executeStatement($query['sql'], $query['params']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$conn->commit();
|
private function transferWorkflowsSQL(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete): void
|
||||||
} catch (\Exception $e) {
|
|
||||||
dump($e->getMessage());
|
|
||||||
$conn->rollBack();
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function transferWorkflowsSQL(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete): array
|
|
||||||
{
|
{
|
||||||
$queries = [];
|
$this->em->getConnection()->executeQuery(
|
||||||
$queries[] = [
|
"UPDATE chill_main_workflow_entity w
|
||||||
'sql' => "UPDATE chill_main_workflow_entity w
|
|
||||||
SET relatedentityid = :toKeepId
|
SET relatedentityid = :toKeepId
|
||||||
WHERE w.relatedentityid = :toDeleteId
|
WHERE w.relatedentityid = :toDeleteId
|
||||||
AND w.relatedentityclass = 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork'",
|
AND w.relatedentityclass = 'Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWork'",
|
||||||
'params' => ['toKeepId' => $toKeep->getId(), 'toDeleteId' => $toDelete->getId()],
|
['toKeepId' => $toKeep->getId(), 'toDeleteId' => $toDelete->getId()]
|
||||||
];
|
);
|
||||||
|
|
||||||
return $queries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generateStartDateSQL(AccompanyingPeriodWork $toDelete, AccompanyingPeriodWork $toKeep): array
|
private function alterStartDate(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete): void
|
||||||
{
|
{
|
||||||
$queries = [];
|
$startDate = min($toKeep->getStartDate(), $toDelete->getStartDate());
|
||||||
$queries[] = [
|
$toKeep->setStartDate($startDate);
|
||||||
'sql' => 'UPDATE chill_person_accompanying_period_work
|
|
||||||
SET startdate = LEAST(
|
|
||||||
COALESCE((SELECT startdate FROM chill_person_accompanying_period_work WHERE id = :toDelete), startdate),
|
|
||||||
startdate
|
|
||||||
)
|
|
||||||
WHERE id = :toKeep',
|
|
||||||
'params' => ['toDelete' => $toDelete->getId(), 'toKeep' => $toKeep->getId()],
|
|
||||||
];
|
|
||||||
|
|
||||||
return $queries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generateEndDateSQL(AccompanyingPeriodWork $toDelete, AccompanyingPeriodWork $toKeep): array
|
private function alterEndDate(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete): void
|
||||||
{
|
{
|
||||||
$queries = [];
|
if (null === $toKeep->getEndDate() || null === $toDelete->getEndDate()) {
|
||||||
$queries[] = [
|
$toKeep->setEndDate(null);
|
||||||
'sql' => '
|
|
||||||
UPDATE chill_person_accompanying_period_work
|
|
||||||
SET enddate =
|
|
||||||
CASE
|
|
||||||
WHEN (SELECT enddate FROM chill_person_accompanying_period_work WHERE id = :toDelete) IS NULL
|
|
||||||
OR enddate IS NULL
|
|
||||||
THEN NULL
|
|
||||||
ELSE GREATEST(
|
|
||||||
COALESCE((SELECT enddate FROM chill_person_accompanying_period_work WHERE id = :toDelete), enddate),
|
|
||||||
enddate
|
|
||||||
)
|
|
||||||
END
|
|
||||||
WHERE id = :toKeep',
|
|
||||||
'params' => ['toDelete' => $toDelete->getId(), 'toKeep' => $toKeep->getId()],
|
|
||||||
|
|
||||||
];
|
return;
|
||||||
|
|
||||||
return $queries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generateCommentSQL(AccompanyingPeriodWork $toDelete, AccompanyingPeriodWork $toKeep): array
|
$endDate = max($toKeep->getEndDate(), $toDelete->getEndDate());
|
||||||
|
$toKeep->setEndDate($endDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function concatenateComments(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete): void
|
||||||
{
|
{
|
||||||
$queries = [];
|
$toKeep->setNote($toKeep->getNote()."\n\n-----------------\n\n".$toDelete->getNote());
|
||||||
$queries[] = [
|
$toKeep->getPrivateComment()->concatenateComments($toDelete->getPrivateComment());
|
||||||
'sql' => "WITH updated_values AS (
|
|
||||||
SELECT
|
|
||||||
acpw1.id AS to_update,
|
|
||||||
acpw1.note || ' ' || acpw2.note AS new_note,
|
|
||||||
jsonb_set(
|
|
||||||
acpw1.privatecomment_comments::jsonb,
|
|
||||||
'{1}',
|
|
||||||
to_jsonb((acpw1.privatecomment_comments::jsonb->>'1') || ' ' || (acpw2.privatecomment_comments::jsonb->>'1'))
|
|
||||||
) AS new_privatecomment_comments
|
|
||||||
FROM
|
|
||||||
chill_person_accompanying_period_work acpw1,
|
|
||||||
chill_person_accompanying_period_work acpw2
|
|
||||||
WHERE
|
|
||||||
acpw1.id = :toKeep AND
|
|
||||||
acpw2.id = :toDelete
|
|
||||||
)
|
|
||||||
UPDATE chill_person_accompanying_period_work
|
|
||||||
SET
|
|
||||||
note = updated_values.new_note,
|
|
||||||
privatecomment_comments = updated_values.new_privatecomment_comments
|
|
||||||
FROM
|
|
||||||
updated_values
|
|
||||||
WHERE
|
|
||||||
chill_person_accompanying_period_work.id = updated_values.to_update",
|
|
||||||
'params' => ['toDelete' => $toDelete->getId(), 'toKeep' => $toKeep->getId()],
|
|
||||||
];
|
|
||||||
|
|
||||||
return $queries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateReferencesSQL(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete): array
|
private function updateReferencesSQL(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete): void
|
||||||
{
|
{
|
||||||
$queries = [];
|
foreach ($toDelete->getAccompanyingPeriodWorkEvaluations() as $evaluation) {
|
||||||
$allMeta = $this->em->getMetadataFactory()->getAllMetadata();
|
$toKeep->addAccompanyingPeriodWorkEvaluation($evaluation);
|
||||||
|
|
||||||
foreach ($allMeta as $meta) {
|
|
||||||
if ($meta->isMappedSuperclass) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$tableName = $meta->getTableName();
|
foreach ($toDelete->getReferrers() as $referrer) {
|
||||||
foreach ($meta->getAssociationMappings() as $assoc) {
|
// we only keep the current referrer
|
||||||
|
$toKeep->addReferrer($referrer);
|
||||||
if (AccompanyingPeriodWork::class !== $assoc['targetEntity'] && AccompanyingPeriodWork::class !== $assoc['sourceEntity']) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($assoc['type'] & ClassMetadata::TO_ONE) !== 0) {
|
foreach ($toDelete->getPersons() as $person) {
|
||||||
$joinColumn = $meta->getSingleAssociationJoinColumnName($assoc['fieldName']);
|
$toKeep->addPerson($person);
|
||||||
|
|
||||||
if (AccompanyingPeriodWorkReferrerHistory::class === $assoc['sourceEntity']) {
|
|
||||||
$queries[] = [
|
|
||||||
'sql' => "DELETE FROM {$tableName} WHERE {$joinColumn} = :toDelete",
|
|
||||||
'params' => ['toKeep' => $toKeep->getId(), 'toDelete' => $toDelete->getId()],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$queries[] = [
|
if (null === $toKeep->getHandlingThierParty()) {
|
||||||
'sql' => "UPDATE {$tableName} SET {$joinColumn} = :toKeep WHERE {$joinColumn} = :toDelete",
|
$toKeep->setHandlingThierParty($toDelete->getHandlingThierParty());
|
||||||
'params' => ['toKeep' => $toKeep->getId(), 'toDelete' => $toDelete->getId()],
|
|
||||||
];
|
|
||||||
} elseif (8 === $assoc['type'] && isset($assoc['joinTable'])) {
|
|
||||||
if ($assoc['isOwningSide']) {
|
|
||||||
dump($assoc);
|
|
||||||
$joinTable = $assoc['joinTable']['name'];
|
|
||||||
$joinColumn = $assoc['joinTable']['joinColumns'][0]['name'];
|
|
||||||
$relationColumn = $assoc['joinTable']['inverseJoinColumns'][0]['name'];
|
|
||||||
$queries[] = [
|
|
||||||
'sql' => "
|
|
||||||
UPDATE {$joinTable} SET {$joinColumn} = :toKeep
|
|
||||||
WHERE {$joinColumn} = :toDelete
|
|
||||||
AND NOT EXISTS (
|
|
||||||
SELECT 1
|
|
||||||
FROM {$joinTable} AS t2
|
|
||||||
WHERE t2.{$joinColumn} = :toKeep
|
|
||||||
AND t2.{$relationColumn} = {$joinTable}.{$relationColumn}
|
|
||||||
)
|
|
||||||
",
|
|
||||||
'params' => ['toDelete' => $toDelete->getId(), 'toKeep' => $toKeep->getId()],
|
|
||||||
];
|
|
||||||
|
|
||||||
$queries[] = [
|
|
||||||
'sql' => "DELETE FROM {$joinTable} WHERE {$joinColumn} = :toDelete",
|
|
||||||
'params' => ['toDelete' => $toDelete->getId()],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $queries;
|
foreach ($toDelete->getThirdParties() as $thirdParty) {
|
||||||
}
|
$toKeep->addThirdParty($thirdParty);
|
||||||
|
}
|
||||||
public function removeAccompanyingPeriodWork(AccompanyingPeriodWork $toDelete): array
|
|
||||||
{
|
|
||||||
return [[
|
|
||||||
'sql' => 'DELETE FROM chill_person_accompanying_period_work WHERE id = :toDelete',
|
|
||||||
'params' => ['toDelete' => $toDelete->getId()],
|
|
||||||
]];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,198 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Chill is a software for social workers
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view
|
||||||
|
* the LICENSE file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Chill\PersonBundle\Tests\Service\AccompanyingPeriodWork;
|
||||||
|
|
||||||
|
use Chill\MainBundle\Entity\User;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
|
||||||
|
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
|
||||||
|
use Chill\PersonBundle\Service\AccompanyingPeriodWork\AccompanyingPeriodWorkMergeService;
|
||||||
|
use Chill\ThirdPartyBundle\Entity\ThirdParty;
|
||||||
|
use Doctrine\DBAL\Connection;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Monolog\Test\TestCase;
|
||||||
|
use Prophecy\Argument;
|
||||||
|
use Prophecy\PhpUnit\ProphecyTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*
|
||||||
|
* @coversNothing
|
||||||
|
*/
|
||||||
|
class AccompanyingPeriodWorkMergeServiceTest extends TestCase
|
||||||
|
{
|
||||||
|
use ProphecyTrait;
|
||||||
|
|
||||||
|
private function buildMergeService(AccompanyingPeriodWork $toRemove): AccompanyingPeriodWorkMergeService
|
||||||
|
{
|
||||||
|
$entityManager = $this->prophesize(EntityManagerInterface::class);
|
||||||
|
$entityManager->wrapInTransaction(Argument::type('callable'))->will(function ($args) use ($entityManager) {
|
||||||
|
call_user_func_array($args[0], [$entityManager->reveal()]);
|
||||||
|
})->shouldBeCalled();
|
||||||
|
$entityManager->remove($toRemove)->shouldBeCalled();
|
||||||
|
|
||||||
|
$connection = $this->prophesize(Connection::class);
|
||||||
|
$connection->executeQuery(Argument::type('string'), Argument::type('array'))->shouldBeCalled();
|
||||||
|
|
||||||
|
$entityManager->getConnection()->willReturn($connection->reveal());
|
||||||
|
|
||||||
|
return new AccompanyingPeriodWorkMergeService($entityManager->reveal());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideStartDateMoveData
|
||||||
|
*/
|
||||||
|
public function testStartDateMove(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete, ?\DateTime $expected): void
|
||||||
|
{
|
||||||
|
$service = $this->buildMergeService($toDelete);
|
||||||
|
$return = $service->merge($toKeep, $toDelete);
|
||||||
|
|
||||||
|
self::assertEquals($expected, $return->getStartDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function provideStartDateMoveData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'Earliest date kept when toKeep is earlier' => [
|
||||||
|
(new AccompanyingPeriodWork())->setStartDate(new \DateTime('2023-01-01')),
|
||||||
|
(new AccompanyingPeriodWork())->setStartDate(new \DateTime('2023-06-01')),
|
||||||
|
new \DateTime('2023-01-01'),
|
||||||
|
],
|
||||||
|
'Earliest date kept when toDelete is earlier' => [
|
||||||
|
(new AccompanyingPeriodWork())->setStartDate(new \DateTime('2023-06-01')),
|
||||||
|
(new AccompanyingPeriodWork())->setStartDate(new \DateTime('2023-01-01')),
|
||||||
|
new \DateTime('2023-01-01'),
|
||||||
|
],
|
||||||
|
'Same start dates remain unchanged' => [
|
||||||
|
(new AccompanyingPeriodWork())->setStartDate(new \DateTime('2023-01-01')),
|
||||||
|
(new AccompanyingPeriodWork())->setStartDate(new \DateTime('2023-01-01')),
|
||||||
|
new \DateTime('2023-01-01'),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideEndDateMoveData
|
||||||
|
*/
|
||||||
|
public function testEndDateMove(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete, ?\DateTimeImmutable $expected): void
|
||||||
|
{
|
||||||
|
$service = $this->buildMergeService($toDelete);
|
||||||
|
$return = $service->merge($toKeep, $toDelete);
|
||||||
|
|
||||||
|
self::assertEquals($expected, $return->getEndDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function provideEndDateMoveData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'Oldest date kept when toKeep is older' => [
|
||||||
|
(new AccompanyingPeriodWork())->setEndDate(new \DateTimeImmutable('2022-01-01'))->setStartDate(new \DateTime('2021-01-01')),
|
||||||
|
(new AccompanyingPeriodWork())->setEndDate(new \DateTimeImmutable('2023-06-01'))->setStartDate(new \DateTime('2021-01-01')),
|
||||||
|
new \DateTimeImmutable('2023-06-01'),
|
||||||
|
],
|
||||||
|
'Oldest date kept when toDelete is older' => [
|
||||||
|
(new AccompanyingPeriodWork())->setEndDate(new \DateTimeImmutable('2023-06-01'))->setStartDate(new \DateTime('2021-01-01')),
|
||||||
|
(new AccompanyingPeriodWork())->setEndDate(new \DateTimeImmutable('2022-01-01'))->setStartDate(new \DateTime('2021-01-01')),
|
||||||
|
new \DateTimeImmutable('2023-06-01'),
|
||||||
|
],
|
||||||
|
'Same end dates remain unchanged' => [
|
||||||
|
(new AccompanyingPeriodWork())->setEndDate(new \DateTimeImmutable('2023-01-01'))->setStartDate(new \DateTime('2021-01-01')),
|
||||||
|
(new AccompanyingPeriodWork())->setEndDate(new \DateTimeImmutable('2023-01-01'))->setStartDate(new \DateTime('2021-01-01')),
|
||||||
|
new \DateTimeImmutable('2023-01-01'),
|
||||||
|
],
|
||||||
|
'End date is null if toKeep is null' => [
|
||||||
|
(new AccompanyingPeriodWork())->setEndDate(null)->setStartDate(new \DateTime('2021-01-01')),
|
||||||
|
(new AccompanyingPeriodWork())->setEndDate(new \DateTimeImmutable('2023-01-01'))->setStartDate(new \DateTime('2021-01-01')),
|
||||||
|
null,
|
||||||
|
],
|
||||||
|
'End date is null if toDelete is null' => [
|
||||||
|
(new AccompanyingPeriodWork())->setEndDate(new \DateTimeImmutable('2023-01-01'))->setStartDate(new \DateTime('2021-01-01')),
|
||||||
|
(new AccompanyingPeriodWork())->setEndDate(null)->setStartDate(new \DateTime('2021-01-01')),
|
||||||
|
null,
|
||||||
|
],
|
||||||
|
'End date is null if both are null' => [
|
||||||
|
(new AccompanyingPeriodWork())->setEndDate(null)->setStartDate(new \DateTime('2021-01-01')),
|
||||||
|
(new AccompanyingPeriodWork())->setEndDate(null)->setStartDate(new \DateTime('2021-01-01')),
|
||||||
|
null,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideMoveHandlingThirdPartyData
|
||||||
|
*/
|
||||||
|
public function testMoveHandlingThirdParty(AccompanyingPeriodWork $toKeep, AccompanyingPeriodWork $toDelete, ?ThirdParty $expected): void
|
||||||
|
{
|
||||||
|
$service = $this->buildMergeService($toDelete);
|
||||||
|
$return = $service->merge($toKeep, $toDelete);
|
||||||
|
|
||||||
|
self::assertSame($expected, $return->getHandlingThierParty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function provideMoveHandlingThirdPartyData(): iterable
|
||||||
|
{
|
||||||
|
yield 'Third party not change when existing in kept' => [
|
||||||
|
(new AccompanyingPeriodWork())->setStartDate(new \DateTimeImmutable('2022-01-01'))->setHandlingThierParty($tpA = new ThirdParty()),
|
||||||
|
(new AccompanyingPeriodWork())->setStartDate(new \DateTimeImmutable('2022-01-01'))->setHandlingThierParty(new ThirdParty()),
|
||||||
|
$tpA,
|
||||||
|
];
|
||||||
|
|
||||||
|
yield 'Third party will change when not existing in kept' => [
|
||||||
|
(new AccompanyingPeriodWork())->setStartDate(new \DateTimeImmutable('2022-01-01')),
|
||||||
|
(new AccompanyingPeriodWork())->setStartDate(new \DateTimeImmutable('2022-01-01'))->setHandlingThierParty($tpB = new ThirdParty()),
|
||||||
|
$tpB,
|
||||||
|
];
|
||||||
|
|
||||||
|
yield 'Third party do not change when not existing in removed' => [
|
||||||
|
(new AccompanyingPeriodWork())->setStartDate(new \DateTimeImmutable('2022-01-01'))->setHandlingThierParty($tpC = new ThirdParty()),
|
||||||
|
(new AccompanyingPeriodWork())->setStartDate(new \DateTimeImmutable('2022-01-01')),
|
||||||
|
$tpC,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMerge(): void
|
||||||
|
{
|
||||||
|
$accompanyingPeriodWork = new AccompanyingPeriodWork();
|
||||||
|
$accompanyingPeriodWork->setStartDate(new \DateTime('2022-01-01'));
|
||||||
|
$accompanyingPeriodWork->addReferrer($userA = new User());
|
||||||
|
$accompanyingPeriodWork->addReferrer($userC = new User());
|
||||||
|
$accompanyingPeriodWork->addAccompanyingPeriodWorkEvaluation($evaluationA = new AccompanyingPeriodWorkEvaluation());
|
||||||
|
$accompanyingPeriodWork->setNote('blabla');
|
||||||
|
$accompanyingPeriodWork->addThirdParty($thirdPartyA = new ThirdParty());
|
||||||
|
|
||||||
|
$toDelete = new AccompanyingPeriodWork();
|
||||||
|
$toDelete->setStartDate(new \DateTime('2022-01-01'));
|
||||||
|
$toDelete->addReferrer($userB = new User());
|
||||||
|
$toDelete->addReferrer($userC);
|
||||||
|
$toDelete->addAccompanyingPeriodWorkEvaluation($evaluationB = new AccompanyingPeriodWorkEvaluation());
|
||||||
|
$toDelete->setNote('boum');
|
||||||
|
$toDelete->addThirdParty($thirdPartyB = new ThirdParty());
|
||||||
|
|
||||||
|
$service = $this->buildMergeService($toDelete);
|
||||||
|
$service->merge($accompanyingPeriodWork, $toDelete);
|
||||||
|
|
||||||
|
self::assertTrue($accompanyingPeriodWork->getReferrers()->contains($userA));
|
||||||
|
self::assertTrue($accompanyingPeriodWork->getReferrers()->contains($userB));
|
||||||
|
self::assertTrue($accompanyingPeriodWork->getReferrers()->contains($userC));
|
||||||
|
|
||||||
|
self::assertTrue($accompanyingPeriodWork->getAccompanyingPeriodWorkEvaluations()->contains($evaluationA));
|
||||||
|
self::assertTrue($accompanyingPeriodWork->getAccompanyingPeriodWorkEvaluations()->contains($evaluationB));
|
||||||
|
foreach ($accompanyingPeriodWork->getAccompanyingPeriodWorkEvaluations() as $evaluation) {
|
||||||
|
self::assertSame($accompanyingPeriodWork, $evaluation->getAccompanyingPeriodWork());
|
||||||
|
}
|
||||||
|
|
||||||
|
self::assertStringContainsString('blabla', $accompanyingPeriodWork->getNote());
|
||||||
|
self::assertStringContainsString('boum', $toDelete->getNote());
|
||||||
|
|
||||||
|
self::assertTrue($accompanyingPeriodWork->getThirdParties()->contains($thirdPartyA));
|
||||||
|
self::assertTrue($accompanyingPeriodWork->getThirdParties()->contains($thirdPartyB));
|
||||||
|
}
|
||||||
|
}
|
@ -66,6 +66,6 @@ module.exports = function (encore, entries) {
|
|||||||
);
|
);
|
||||||
encore.addEntry(
|
encore.addEntry(
|
||||||
"mod_duplicate_selector",
|
"mod_duplicate_selector",
|
||||||
__dirname + "/Resources/public/mod/DuplicateSelector/AccompanyingPeriodWorkSelector.js",
|
__dirname + "/Resources/public/mod/DuplicateSelector/AccompanyingPeriodWorkSelector.ts",
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user