From 611a968162c66f30f4510946e25488e662155eff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 23 Sep 2024 16:32:47 +0200 Subject: [PATCH] Duplicate and accompanying course evaluation document - create a service which duplicate the accompanying course work evaluation document - create a controller to duplicate this document - update the vuejs component to use this duplicate action --- ...companyingCourseDocumentDuplicatorTest.php | 2 - .../AccompanyingCourseDocumentDuplicator.php | 3 - ...ompanyingCourseDocumentWorkflowHandler.php | 5 +- ...kEvaluationDocumentDuplicateController.php | 55 ++++++++++++++++++ .../Resources/public/types.ts | 23 +++++++- .../components/FormEvaluation.vue | 6 ++ .../vuejs/AccompanyingCourseWorkEdit/store.js | 13 +++++ ...ccompanyingCourseWorkEvaluationDocument.ts | 6 ++ ...PeriodWorkEvaluationDocumentDuplicator.php | 39 +++++++++++++ ...odWorkEvaluationDocumentDuplicatorTest.php | 57 +++++++++++++++++++ .../ChillPersonBundle/chill.api.specs.yaml | 22 +++++++ .../translations/messages+intl-icu.fr.yaml | 8 ++- 12 files changed, 228 insertions(+), 11 deletions(-) create mode 100644 src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationDocumentDuplicateController.php create mode 100644 src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/accompanyingCourseWorkEvaluationDocument.ts create mode 100644 src/Bundle/ChillPersonBundle/Service/AccompanyingPeriodWorkEvaluationDocument/AccompanyingPeriodWorkEvaluationDocumentDuplicator.php create mode 100644 src/Bundle/ChillPersonBundle/Tests/Service/AccompanyingPeriodWorkEvaluationDocument/AccompanyingPeriodWorkEvaluationDocumentDuplicatorTest.php diff --git a/src/Bundle/ChillDocStoreBundle/Tests/Workflow/AccompanyingCourseDocumentDuplicatorTest.php b/src/Bundle/ChillDocStoreBundle/Tests/Workflow/AccompanyingCourseDocumentDuplicatorTest.php index fd920c7a9..71df75d20 100644 --- a/src/Bundle/ChillDocStoreBundle/Tests/Workflow/AccompanyingCourseDocumentDuplicatorTest.php +++ b/src/Bundle/ChillDocStoreBundle/Tests/Workflow/AccompanyingCourseDocumentDuplicatorTest.php @@ -19,8 +19,6 @@ use Chill\DocStoreBundle\Workflow\AccompanyingCourseDocumentDuplicator; use Chill\MainBundle\Entity\User; use PHPUnit\Framework\TestCase; use Symfony\Component\Clock\MockClock; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Security\Core\Security; use Symfony\Contracts\Translation\TranslatorInterface; /** diff --git a/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentDuplicator.php b/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentDuplicator.php index b4c15fc22..22ee65cc3 100644 --- a/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentDuplicator.php +++ b/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentDuplicator.php @@ -12,11 +12,8 @@ declare(strict_types=1); namespace Chill\DocStoreBundle\Workflow; use Chill\DocStoreBundle\Entity\AccompanyingCourseDocument; -use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter; use Chill\DocStoreBundle\Service\StoredObjectDuplicate; use Symfony\Component\Clock\ClockInterface; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Security\Core\Security; use Symfony\Contracts\Translation\TranslatorInterface; /** diff --git a/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentWorkflowHandler.php b/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentWorkflowHandler.php index ba7c477e5..bc8de6587 100644 --- a/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentWorkflowHandler.php +++ b/src/Bundle/ChillDocStoreBundle/Workflow/AccompanyingCourseDocumentWorkflowHandler.php @@ -17,7 +17,6 @@ use Chill\DocStoreBundle\Entity\StoredObject; use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter; use Chill\MainBundle\Entity\Workflow\EntityWorkflow; use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository; -use Chill\MainBundle\Workflow\EntityWorkflowWithDuplicableRelatedEntityInterface; use Chill\MainBundle\Workflow\EntityWorkflowWithStoredObjectHandlerInterface; use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation; use Symfony\Contracts\Translation\TranslatorInterface; @@ -28,8 +27,8 @@ use Symfony\Contracts\Translation\TranslatorInterface; readonly class AccompanyingCourseDocumentWorkflowHandler implements EntityWorkflowWithStoredObjectHandlerInterface { public function __construct( - private TranslatorInterface $translator, - private EntityWorkflowRepository $workflowRepository, + private TranslatorInterface $translator, + private EntityWorkflowRepository $workflowRepository, private AccompanyingCourseDocumentRepository $repository, ) {} diff --git a/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationDocumentDuplicateController.php b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationDocumentDuplicateController.php new file mode 100644 index 000000000..ec48b5b24 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Controller/AccompanyingPeriodWorkEvaluationDocumentDuplicateController.php @@ -0,0 +1,55 @@ +getAccompanyingPeriodWorkEvaluation()->getAccompanyingPeriodWork(); + + if (!$this->security->isGranted(AccompanyingPeriodWorkVoter::UPDATE, $work)) { + throw new AccessDeniedHttpException('not allowed to edit this accompanying period work'); + } + + $duplicatedDocument = $this->duplicator->duplicate($document); + + $this->entityManager->persist($duplicatedDocument); + $this->entityManager->persist($duplicatedDocument->getStoredObject()); + $this->entityManager->flush(); + + return new JsonResponse( + $this->serializer->serialize($duplicatedDocument, 'json', [AbstractNormalizer::GROUPS => ['read']]), + json: true + ); + } +} diff --git a/src/Bundle/ChillPersonBundle/Resources/public/types.ts b/src/Bundle/ChillPersonBundle/Resources/public/types.ts index 755c23e2d..aae801fc3 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/types.ts +++ b/src/Bundle/ChillPersonBundle/Resources/public/types.ts @@ -1,4 +1,12 @@ -import {Address, Center, Civility, DateTime} from "../../../ChillMainBundle/Resources/public/types"; +import { + Address, + Center, + Civility, + DateTime, + User, + WorkflowAvailable +} from "../../../ChillMainBundle/Resources/public/types"; +import {StoredObject} from "../../../ChillDocStoreBundle/Resources/public/types"; export interface Person { id: number; @@ -20,3 +28,16 @@ export interface Person { current_household_id: number; current_residential_addresses: Address[]; } + +export interface AccompanyingPeriodWorkEvaluationDocument { + id: number; + type: "accompanying_period_work_evaluation_document" + storedObject: StoredObject; + title: string; + createdAt: DateTime | null; + createdBy: User | null; + updatedAt: DateTime | null; + updatedBy: User | null; + workflows_availables: WorkflowAvailable[]; + workflows: object[]; +} diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue index 0c0cc22cb..dbc53c4e8 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/components/FormEvaluation.vue @@ -147,6 +147,9 @@ +
  • + +
  • @@ -396,6 +399,9 @@ export default { this.$store.commit('removeDocument', {key: this.evaluation.key, document: document}); } }, + duplicateDocument(document) { + this.$store.dispatch('duplicateDocument', {evaluation_key: this.evaluation.key, document: document}); + }, onStatusDocumentChanged(newStatus) { console.log('onStatusDocumentChanged', newStatus); this.$store.commit('statusDocumentChanged', {key: this.evaluation.key, newStatus: newStatus}); diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/store.js b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/store.js index 236c77140..4279aa366 100644 --- a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/store.js +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/AccompanyingCourseWorkEdit/store.js @@ -4,6 +4,7 @@ import { findSocialActionsBySocialIssue } from 'ChillPersonAssets/vuejs/_api/Soc import { create } from 'ChillPersonAssets/vuejs/_api/AccompanyingCourseWork.js'; import { fetchResults, makeFetch } from 'ChillMainAssets/lib/api/apiMethods.ts'; import { fetchTemplates } from 'ChillDocGeneratorAssets/api/pickTemplate.js'; +import { duplicate } from '../_api/accompanyingCourseWorkEvaluationDocument'; const debug = process.env.NODE_ENV !== 'production'; const evalFQDN = encodeURIComponent("Chill\\PersonBundle\\Entity\\AccompanyingPeriod\\AccompanyingPeriodWorkEvaluation"); @@ -238,6 +239,14 @@ const store = createStore({ } evaluation.documents = evaluation.documents.filter(d => d.key !== document.key); }, + addDuplicatedDocument(state, {document, evaluation_key}) { + console.log('add duplicated document', document); + console.log('add duplicated dcuemnt - evaluation key', evaluation_key); + + let evaluation = state.evaluationsPicked.find(e => e.key === evaluation_key); + document.key = evaluation.documents.length + 1; + evaluation.documents.splice(0, 0, document); + }, /** * Replaces a document in the state with a new document. * @@ -506,6 +515,10 @@ const store = createStore({ addDocument({commit}, payload) { commit('addDocument', payload); }, + async duplicateDocument({commit}, {document, evaluation_key}) { + const newDoc = await duplicate(document.id); + commit('addDuplicatedDocument', {document: newDoc, evaluation_key}); + }, removeDocument({commit}, payload) { commit('removeDocument', payload); }, diff --git a/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/accompanyingCourseWorkEvaluationDocument.ts b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/accompanyingCourseWorkEvaluationDocument.ts new file mode 100644 index 000000000..a7c03e5ea --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Resources/public/vuejs/_api/accompanyingCourseWorkEvaluationDocument.ts @@ -0,0 +1,6 @@ +import {AccompanyingPeriodWorkEvaluationDocument} from "../../types"; +import {makeFetch} from "../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods"; + +export const duplicate = async (id: number): Promise => { + return makeFetch("POST", `/api/1.0/person/accompanying-course-work-evaluation-document/${id}/duplicate`); +} diff --git a/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriodWorkEvaluationDocument/AccompanyingPeriodWorkEvaluationDocumentDuplicator.php b/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriodWorkEvaluationDocument/AccompanyingPeriodWorkEvaluationDocumentDuplicator.php new file mode 100644 index 000000000..5ca37aa71 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Service/AccompanyingPeriodWorkEvaluationDocument/AccompanyingPeriodWorkEvaluationDocumentDuplicator.php @@ -0,0 +1,39 @@ +setTitle($document->getTitle().' ('.$this->translator->trans('accompanying_course_evaluation_document.duplicated_at', ['at' => $this->clock->now()]).')') + ->setStoredObject($this->storedObjectDuplicate->duplicate($document->getStoredObject())) + ; + + $document->getAccompanyingPeriodWorkEvaluation()->addDocument($newDocument); + + return $newDocument; + } +} diff --git a/src/Bundle/ChillPersonBundle/Tests/Service/AccompanyingPeriodWorkEvaluationDocument/AccompanyingPeriodWorkEvaluationDocumentDuplicatorTest.php b/src/Bundle/ChillPersonBundle/Tests/Service/AccompanyingPeriodWorkEvaluationDocument/AccompanyingPeriodWorkEvaluationDocumentDuplicatorTest.php new file mode 100644 index 000000000..e24caef63 --- /dev/null +++ b/src/Bundle/ChillPersonBundle/Tests/Service/AccompanyingPeriodWorkEvaluationDocument/AccompanyingPeriodWorkEvaluationDocumentDuplicatorTest.php @@ -0,0 +1,57 @@ +setStoredObject($storedObject) + ->setTitle('test title') + ->setAccompanyingPeriodWorkEvaluation($evaluation); + + $storedObjectDuplicator = $this->createMock(StoredObjectDuplicate::class); + $storedObjectDuplicator->expects($this->once())->method('duplicate')->with($storedObject)->willReturn($newStoredObject = new StoredObject()); + + $translator = $this->createMock(TranslatorInterface::class); + $translator->method('trans')->willReturn('test translated'); + + $clock = new MockClock(); + + $duplicator = new AccompanyingPeriodWorkEvaluationDocumentDuplicator($storedObjectDuplicator, $translator, $clock); + + $actual = $duplicator->duplicate($document); + + self::assertNotSame($document, $actual); + self::assertStringStartsWith('test title', $actual->getTitle()); + self::assertSame($newStoredObject, $actual->getStoredObject()); + self::assertSame($evaluation, $actual->getAccompanyingPeriodWorkEvaluation()); + } +} diff --git a/src/Bundle/ChillPersonBundle/chill.api.specs.yaml b/src/Bundle/ChillPersonBundle/chill.api.specs.yaml index 72a4b78e3..45cccf958 100644 --- a/src/Bundle/ChillPersonBundle/chill.api.specs.yaml +++ b/src/Bundle/ChillPersonBundle/chill.api.specs.yaml @@ -1948,3 +1948,25 @@ paths: responses: 200: description: "OK" + + /1.0/person/accompanying-course-work-evaluation-document/{id}/duplicate: + post: + tags: + - accompanying-course-work-evaluation-document + summary: Dupliate an an accompanying period work evaluation document + parameters: + - in: path + name: id + required: true + description: The document's id + schema: + type: integer + format: integer + minimum: 1 + responses: + 200: + description: "OK" + content: + application/json: + schema: + type: object diff --git a/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml b/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml index 9b2edf573..3ea21e06d 100644 --- a/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml +++ b/src/Bundle/ChillPersonBundle/translations/messages+intl-icu.fr.yaml @@ -163,8 +163,8 @@ exports: { total, plural, =0 {Aucun usager ne correspond aux termes de recherche} one {Un usager correspond aux termes de recherche} - many {# usagers correspondent aux terms de recherche} - other {# usagers correspondent aux terms de recherche} + many {# usagers correspondent aux termes de recherche} + other {# usagers correspondent aux termes de recherche} } 'nb person with similar name. Please verify that this is a new person': >- @@ -173,3 +173,7 @@ exports: one {Un usager a un nom similaire. Vérifiez qu'il ne s'agit pas de lui.} other {# usagers ont un nom similaire. Vérifiez qu'il ne s'agit pas de l'un d'eux} } + +accompanying_course_evaluation_document: + duplicated_at: >- + Dupliqué le {at, date, long} à {at, time, short}