Merge remote-tracking branch 'origin/master'

This commit is contained in:
Julien Fastré 2021-08-20 13:01:03 +02:00
commit 176b68417a
10 changed files with 204 additions and 40 deletions

View File

@ -3,6 +3,11 @@
namespace Chill\DocGeneratorBundle\Controller; namespace Chill\DocGeneratorBundle\Controller;
use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepository; use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepository;
use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
use Chill\PersonBundle\Entity\SocialWork\Evaluation;
use GuzzleHttp\Exception\TransferException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\JsonResponse;
@ -54,7 +59,7 @@ class DocGeneratorTemplateController extends AbstractController
* ) * )
*/ */
public function generateDocFromTemplateAction( public function generateDocFromTemplateAction(
TempUrlOpenstackGenerator $tempUrlGenerator, \ChampsLibres\AsyncUploaderBundle\TempUrl\TempUrlGeneratorInterface $tempUrlGenerator,
DocGeneratorTemplate $template, string $entityClassName, int $entityId): Response DocGeneratorTemplate $template, string $entityClassName, int $entityId): Response
{ {
$getUrlGen = $tempUrlGenerator->generate( $getUrlGen = $tempUrlGenerator->generate(
@ -87,7 +92,7 @@ class DocGeneratorTemplateController extends AbstractController
$fileContent = fopen($tmpfname2, 'r'); // the generated file content $fileContent = fopen($tmpfname2, 'r'); // the generated file content
$genDocName = 'doc_'.sprintf( '%010d', rand()).'.docx'; $genDocName = 'doc_' . sprintf('%010d', rand()) . '.docx';
$getUrlGen = $tempUrlGenerator->generate( $getUrlGen = $tempUrlGenerator->generate(
'PUT', 'PUT',
@ -97,25 +102,40 @@ class DocGeneratorTemplateController extends AbstractController
$client = new Client(); $client = new Client();
$putResponse = $client->request('PUT', $getUrlGen->{'url'}, [ try {
'body' => $fileContent $putResponse = $client->request('PUT', $getUrlGen->{'url'}, [
]); 'body' => $fileContent
]);
if ($putResponse->getStatusCode() == 201) { if ($putResponse->getStatusCode() == 201) {
return new JsonResponse( $em = $this->getDoctrine()->getManager();
array( $storedObject = new StoredObject();
"msg" => "Document créé", $storedObject
"id" => $genDocName, // currently, only docx is supported
"response" => array( ->setType('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
"reasonPhrase" => $putResponse->getReasonPhrase(), ->setFilename($genDocName);
"statusCode" => $putResponse->getStatusCode())));
$em->persist($storedObject);
// Only for evaluation
if ($entity instanceof AccompanyingPeriodWorkEvaluation) {
$doc = new AccompanyingPeriodWorkEvaluationDocument();
$doc
->setStoredObject($storedObject)
->setTemplate($template)
;
$entity->addDocument($doc);
$em->persist($doc);
}
$em->flush();
return $this->redirectToRoute('chill_wopi_file_edit', [
'fileId' => $genDocName
]);
}
} catch (TransferException $e) {
throw $e;
} }
return new JsonResponse(
array(
"msg" => "PBM",
"response" => array(
"reasonPhrase" => $putResponse->getReasonPhrase(),
"statusCode" => $putResponse->getStatusCode())));
} }
} }

View File

@ -4,11 +4,11 @@ namespace Chill\DocGeneratorBundle\Entity;
use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepository; use Chill\DocGeneratorBundle\Repository\DocGeneratorTemplateRepository;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation as Serializer;
/** /**
* @ORM\Entity * @ORM\Entity
* @ORM\Table(name="chill_docgen_template") * @ORM\Table(name="chill_docgen_template")
*/ */
class DocGeneratorTemplate class DocGeneratorTemplate
{ {
@ -16,11 +16,13 @@ class DocGeneratorTemplate
* @ORM\Id * @ORM\Id
* @ORM\GeneratedValue * @ORM\GeneratedValue
* @ORM\Column(type="integer") * @ORM\Column(type="integer")
* @Serializer\Groups({"read"})
*/ */
private int $id; private int $id;
/** /**
* @ORM\Column(type="json_array") * @ORM\Column(type="json_array")
* @Serializer\Groups({"read"})
*/ */
private array $name = []; private array $name = [];

View File

@ -8,12 +8,11 @@ use Doctrine\ORM\Mapping as ORM;
use ChampsLibres\AsyncUploaderBundle\Model\AsyncFileInterface; use ChampsLibres\AsyncUploaderBundle\Model\AsyncFileInterface;
use ChampsLibres\AsyncUploaderBundle\Validator\Constraints\AsyncFileExists; use ChampsLibres\AsyncUploaderBundle\Validator\Constraints\AsyncFileExists;
use DateTimeInterface; use DateTimeInterface;
use Symfony\Component\Serializer\Annotation as Serializer;
/** /**
* Represent a document stored in an object store * Represent a document stored in an object store
* *
* @author Julien Fastré <julien.fastre@champs-libres.coop>
*
* @ORM\Entity() * @ORM\Entity()
* @ORM\Table("chill_doc.stored_object") * @ORM\Table("chill_doc.stored_object")
* @AsyncFileExists( * @AsyncFileExists(
@ -26,40 +25,45 @@ class StoredObject implements AsyncFileInterface
* @ORM\Id() * @ORM\Id()
* @ORM\GeneratedValue() * @ORM\GeneratedValue()
* @ORM\Column(type="integer") * @ORM\Column(type="integer")
* @Serializer\Groups({"read"})
*/ */
private $id; private $id;
/** /**
* @ORM\Column(type="text") * @ORM\Column(type="text")
* @Serializer\Groups({"read"})
*/ */
private $filename; private $filename;
/** /**
* @ORM\Column(type="json_array", name="key") * @ORM\Column(type="json_array", name="key")
*/ */
private array $keyInfos; private array $keyInfos = [];
/** /**
* *
* @var int[] * @var int[]
* @ORM\Column(type="json_array", name="iv") * @ORM\Column(type="json_array", name="iv")
*/ */
private array $iv; private array $iv = [];
/** /**
* @ORM\Column(type="datetime", name="creation_date") * @ORM\Column(type="datetime", name="creation_date")
* @Serializer\Groups({"read"})
*/ */
private DateTimeInterface $creationDate; private DateTimeInterface $creationDate;
/** /**
* @ORM\Column(type="text", name="type") * @ORM\Column(type="text", name="type")
* @Serializer\Groups({"read"})
*/ */
private string $type = ''; private string $type = '';
/** /**
* @ORM\Column(type="json_array", name="datas") * @ORM\Column(type="json_array", name="datas")
* @Serializer\Groups({"read"})
*/ */
private array $datas; private array $datas = [];
public function __construct() public function __construct()
{ {

View File

@ -94,7 +94,7 @@ const datetimeToISO = (date) => {
const intervalDaysToISO = (days) => { const intervalDaysToISO = (days) => {
if (null === days) { if (null === days) {
return 'PD0'; return 'P0D';
} }
return `P${days}D`; return `P${days}D`;

View File

@ -135,6 +135,7 @@ class AccompanyingPeriodWorkEvaluation implements TrackUpdateInterface, TrackCre
* *
* @Serializer\Groups({"read"}) * @Serializer\Groups({"read"})
* @Serializer\Groups({"write"}) * @Serializer\Groups({"write"})
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
* *
* @var mixed * @var mixed
* *
@ -382,6 +383,22 @@ class AccompanyingPeriodWorkEvaluation implements TrackUpdateInterface, TrackCre
return $this->documents; return $this->documents;
} }
public function addDocument(AccompanyingPeriodWorkEvaluationDocument $document): self
{
if (!$this->documents->contains($document)) {
$this->documents[] = $document;
$document->setAccompanyingPeriodWorkEvaluation($this);
}
return $this;
}
public function removeDocument(AccompanyingPeriodWorkEvaluationDocument $document): self
{
$this->documents->removeElement($document);
return $this;
}
/** /**
* Arbitrary data, used for client * Arbitrary data, used for client
* *

View File

@ -2,6 +2,7 @@
namespace Chill\PersonBundle\Entity\AccompanyingPeriod; namespace Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\DocGeneratorBundle\Entity\DocGeneratorTemplate;
use Chill\DocStoreBundle\Entity\StoredObject; use Chill\DocStoreBundle\Entity\StoredObject;
use Chill\MainBundle\Doctrine\Model\TrackCreationInterface; use Chill\MainBundle\Doctrine\Model\TrackCreationInterface;
use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface; use Chill\MainBundle\Doctrine\Model\TrackUpdateInterface;
@ -37,7 +38,7 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
* inversedBy="documents" * inversedBy="documents"
* ) * )
*/ */
private ?AccompanyingPeriodWorkEvaluation $accompanyingPeriodWorkEvaluation; private ?AccompanyingPeriodWorkEvaluation $accompanyingPeriodWorkEvaluation = null;
/** /**
* @ORM\ManyToOne( * @ORM\ManyToOne(
@ -45,13 +46,13 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
* ) * )
* @Serializer\Groups({"read"}) * @Serializer\Groups({"read"})
*/ */
private ?User $createdBy; private ?User $createdBy = null;
/** /**
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) * @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
* @Serializer\Groups({"read"}) * @Serializer\Groups({"read"})
*/ */
private ?\DateTimeImmutable $createdAt; private ?\DateTimeImmutable $createdAt = null;
/** /**
* @ORM\ManyToOne( * @ORM\ManyToOne(
@ -59,18 +60,29 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
* ) * )
* @Serializer\Groups({"read"}) * @Serializer\Groups({"read"})
*/ */
private ?User $updatedBy; private ?User $updatedBy = null;
/** /**
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null}) * @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
* @Serializer\Groups({"read"}) * @Serializer\Groups({"read"})
*/ */
private ?DateTimeImmutable $updatedAt; private ?\DateTimeImmutable $updatedAt = null;
// TODO: indiquer le document généré par le module "document" /**
private ?StoredObject $storedObject; * @ORM\ManyToOne(
* targetEntity=StoredObject::class
* )
* @Serializer\Groups({"read"})
*/
private ?StoredObject $storedObject = null;
// TODO: ajouter gabarit /**
* @ORM\ManyToOne(
* targetEntity=DocGeneratorTemplate::class
* )
* @Serializer\Groups({"read"})
*/
private ?DocGeneratorTemplate $template = null;
/** /**
* @return AccompanyingPeriodWorkEvaluation|null * @return AccompanyingPeriodWorkEvaluation|null
@ -86,6 +98,14 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
*/ */
public function setAccompanyingPeriodWorkEvaluation(?AccompanyingPeriodWorkEvaluation $accompanyingPeriodWorkEvaluation): AccompanyingPeriodWorkEvaluationDocument public function setAccompanyingPeriodWorkEvaluation(?AccompanyingPeriodWorkEvaluation $accompanyingPeriodWorkEvaluation): AccompanyingPeriodWorkEvaluationDocument
{ {
// if an evaluation is already associated, we cannot change the association (removing the association,
// by setting a null value, is allowed.
if ($this->accompanyingPeriodWorkEvaluation instanceof AccompanyingPeriodWorkEvaluation
&& $accompanyingPeriodWorkEvaluation instanceof AccompanyingPeriodWorkEvaluation) {
if ($this->accompanyingPeriodWorkEvaluation !== $accompanyingPeriodWorkEvaluation) {
throw new \RuntimeException("It is not allowed to change the evaluation for a document");
}
}
$this->accompanyingPeriodWorkEvaluation = $accompanyingPeriodWorkEvaluation; $this->accompanyingPeriodWorkEvaluation = $accompanyingPeriodWorkEvaluation;
return $this; return $this;
} }
@ -172,4 +192,22 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
return $this->updatedAt; return $this->updatedAt;
} }
/**
* @return DocGeneratorTemplate|null
*/
public function getTemplate(): ?DocGeneratorTemplate
{
return $this->template;
}
/**
* @param DocGeneratorTemplate|null $template
* @return AccompanyingPeriodWorkEvaluationDocument
*/
public function setTemplate(?DocGeneratorTemplate $template): AccompanyingPeriodWorkEvaluationDocument
{
$this->template = $template;
return $this;
}
} }

View File

@ -19,8 +19,20 @@
<dt v-if="evaluation.warningInterval">{{ $t('warningInterval') }} :</dt> <dt v-if="evaluation.warningInterval">{{ $t('warningInterval') }} :</dt>
<dd v-if="evaluation.warningInterval">{{ evaluation.warningInterval }}</dd> <dd v-if="evaluation.warningInterval">{{ evaluation.warningInterval }}</dd>
<dt v-if="evaluation.documents && evaluation.documents.length > 0">{{ $t('documents') }} :</dt> <template v-if="evaluation.documents.length > 1">
<dd v-if="evaluation.documents && evaluation.documents.length > 0">{{ evaluation.documents.length }}</dd> <dt>{{ $t('documents') }} :</dt>
<dd>
<ul>
<li v-for="d in evaluation.documents" :key="d.id">
{{ d.template.name.fr }}
<a :href="buildEditLink(d.storedObject)" class="btn btn-action btn-sm">
<i class="fa fa-edit"></i>
</a>
</li>
</ul>
</dd>
</template>
</dl> </dl>
<dl class="item-details"> <dl class="item-details">
@ -82,7 +94,7 @@ export default {
computed: { computed: {
pickedEvaluations() { pickedEvaluations() {
return this.$store.state.evaluationsPicked; return this.$store.state.evaluationsPicked;
} },
}, },
methods: { methods: {
removeEvaluation(e) { removeEvaluation(e) {
@ -95,7 +107,10 @@ export default {
}, },
submitForm() { submitForm() {
this.toggleEditEvaluation(); this.toggleEditEvaluation();
} },
buildEditLink(storedObject) {
return `/wopi/edit/${storedObject.filename}`;
},
} }
} }
</script> </script>

View File

@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Add a link between evaluation document, stored object, and document template
*/
final class Version20210820093927 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add a link between evaluation document, stored object, and document template';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document ADD template_id INT DEFAULT NULL');
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document ADD storedObject_id INT DEFAULT NULL');
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document ADD CONSTRAINT FK_33EC92296C99C13A FOREIGN KEY (storedObject_id) REFERENCES chill_doc.stored_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document ADD CONSTRAINT FK_33EC92295DA0FB8 FOREIGN KEY (template_id) REFERENCES chill_docgen_template (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('CREATE INDEX IDX_33EC92296C99C13A ON chill_person_accompanying_period_work_evaluation_document (storedObject_id)');
$this->addSql('CREATE INDEX IDX_33EC92295DA0FB8 ON chill_person_accompanying_period_work_evaluation_document (template_id)');
}
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document DROP CONSTRAINT FK_33EC92296C99C13A');
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document DROP CONSTRAINT FK_33EC92295DA0FB8');
$this->addSql('DROP INDEX IDX_33EC92296C99C13A');
$this->addSql('DROP INDEX IDX_33EC92295DA0FB8');
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document DROP template_id');
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document DROP storedObject_id');
}
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Add missing sequence for evaluation documents
*/
final class Version20210820100407 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add missing sequence for evaluation documents';
}
public function up(Schema $schema): void
{
$this->addSql('CREATE SEQUENCE chill_person_social_work_eval_doc_id_seq INCREMENT BY 1 MINVALUE 1000 START 1000');
}
public function down(Schema $schema): void
{
$this->addSql('DROP SEQUENCE chill_person_social_work_eval_doc_id_seq');
}
}

View File

@ -12,6 +12,6 @@ use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
return static function (RoutingConfigurator $routes) { return static function (RoutingConfigurator $routes) {
$routes $routes
->add('testtest', '/edit/{fileId}') ->add('chill_wopi_file_edit', '/edit/{fileId}')
->controller(Test::class); ->controller(Test::class);
}; };