From 688fdd49ee321b3fa7007eed73006e7e0bf1d785 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 9 Apr 2023 17:56:15 +0200 Subject: [PATCH] add bill categories add webdav client change pdf viewer --- .env | 5 + assets/js/admin.js | 2 + assets/js/modules/pdf-viewer.js | 17 +++ composer.json | 2 +- config/services.yaml | 12 ++ package.json | 1 + src/Api/Webdav/Client.php | 73 ++++++++++ src/Controller/BillAdminController.php | 54 ++++++-- .../BillCategoryAdminController.php | 129 ++++++++++++++++++ src/Entity/Bill.php | 51 +++++++ src/Entity/BillCategory.php | 85 ++++++++++++ src/Entity/BillVendor.php | 4 + src/Factory/BillCategoryFactory.php | 17 +++ src/Factory/BillVendorFactory.php | 4 +- src/Form/BillCategoryType.php | 25 ++++ src/Form/BillFilterType.php | 14 ++ src/Form/BillType.php | 33 +++++ src/Repository/BillCategoryRepository.php | 66 +++++++++ .../BillCategoryRepositoryQuery.php | 15 ++ templates/admin/bill/_form.html.twig | 19 ++- templates/admin/bill/_show.html.twig | 16 ++- templates/admin/menu.html.twig | 33 +++-- yarn.lock | 5 + 23 files changed, 646 insertions(+), 36 deletions(-) create mode 100644 assets/js/modules/pdf-viewer.js create mode 100644 src/Api/Webdav/Client.php create mode 100644 src/Controller/BillCategoryAdminController.php create mode 100644 src/Entity/BillCategory.php create mode 100644 src/Factory/BillCategoryFactory.php create mode 100644 src/Form/BillCategoryType.php create mode 100644 src/Repository/BillCategoryRepository.php create mode 100644 src/Repository/BillCategoryRepositoryQuery.php diff --git a/.env b/.env index 1b3d2df..8683790 100644 --- a/.env +++ b/.env @@ -31,3 +31,8 @@ DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" # DATABASE_URL="mysql://db_user:db_password@127.0.0.1:3306/db_name?serverVersion=5.7" # DATABASE_URL="postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=13&charset=utf8" ###< doctrine/doctrine-bundle ### + +WEBDAV_BILLING_SERVER=https://deblan.cloud +WEBDAV_BILLING_BASE_URL=/public.php/webdav/ +WEBDAV_BILLING_USERNAME= +WEBDAV_BILLING_PASSWORD= diff --git a/assets/js/admin.js b/assets/js/admin.js index 84a0624..cd7e9ed 100644 --- a/assets/js/admin.js +++ b/assets/js/admin.js @@ -4,8 +4,10 @@ const AddressAutocomplete = require('./modules/address.js') const FilesCollectionSorter = require('./modules/collection-sorter.js') const Calendar = require('./modules/calendar.js') const Masks = require('./modules/masks.js') +const PdfViewer = require('./modules/pdf-viewer.js') new AddressAutocomplete() new FilesCollectionSorter() new Calendar() new Masks() +new PdfViewer() diff --git a/assets/js/modules/pdf-viewer.js b/assets/js/modules/pdf-viewer.js new file mode 100644 index 0000000..cc28cab --- /dev/null +++ b/assets/js/modules/pdf-viewer.js @@ -0,0 +1,17 @@ +const viewer = require('pdfobject') + +class PdfViewer { + constructor () { + this.showPdfs() + } + + showPdfs () { + const elements = document.querySelectorAll('*[data-pdf]') + + for (const element of elements) { + viewer.embed(element.getAttribute('data-pdf'), `#${element.getAttribute('id')}`) + } + } +} + +module.exports = PdfViewer diff --git a/composer.json b/composer.json index bc5194f..114c71a 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "doctrine/orm": "2.11.*", "knplabs/knp-snappy": "^1.4", "murph/murph-core": "^1.18", - "sabre/dav": "^4.3" + "sabre/dav": "^4.4" }, "require-dev": { "symfony/browser-kit": "^5.4", diff --git a/config/services.yaml b/config/services.yaml index 4db0e18..71181e8 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -4,6 +4,10 @@ # Put parameters here that don't need to change on each machine where the app is deployed # https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration parameters: + webdav_billing_server: "%env(WEBDAV_BILLING_SERVER)%" + webdav_billing_base_url: "%env(WEBDAV_BILLING_BASE_URL)%" + webdav_billing_username: "%env(WEBDAV_BILLING_USERNAME)%" + webdav_billing_password: "%env(WEBDAV_BILLING_PASSWORD)%" services: # default configuration for services in *this* file @@ -65,5 +69,13 @@ services: $privateKeyPath: '%kernel.project_dir%/config/secrets/prod.private.key' $filesystem: '@filesystem' + App\Api\Webdav\Client: + public: true + arguments: + $server: '%webdav_billing_server%' + $baseUrl: '%webdav_billing_base_url%' + $username: '%webdav_billing_username%' + $password: '%webdav_billing_password%' + # add more service definitions when explicit configuration is needed # please note that last definitions always *replace* previous ones diff --git a/package.json b/package.json index 883eb89..8b0b675 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "chunk": "^0.0.3", "inputmask": "^5.0.8-beta.17", "murph-project": "^1", + "pdfobject": "^2.2.8", "vue-fragment": "^1.5.2" } } diff --git a/src/Api/Webdav/Client.php b/src/Api/Webdav/Client.php new file mode 100644 index 0000000..ae3aaaa --- /dev/null +++ b/src/Api/Webdav/Client.php @@ -0,0 +1,73 @@ + + */ +class Client +{ + protected BaseClient $client; + protected string $baseUrl; + + public function __construct(string $server, string $baseUrl, ?string $username, ?string $password) + { + $settings = [ + 'baseUri' => $server, + 'userName' => $username, + 'password' => $password, + 'authType' => 1, + ]; + + $this->baseUrl = rtrim($baseUrl, '/'); + $this->client = new BaseClient($settings); + } + + public function sendFile(string $localFile, string $remoteFile): array + { + return $this->client->request( + 'PUT', + $this->baseUrl.'/'.$remoteFile, + fopen($localFile, 'r') + ); + } + + public function mv(string $source, string $destination): array + { + return $this->client->request( + 'MOVE', + $this->baseUrl.'/'.$source, + null, + [ + 'Destination' => $this->baseUrl.'/'.$destination, + ] + ); + } + + public function mkdir(string $directory): array + { + return $this->client->request( + 'MKCOL', + $this->baseUrl.'/'.$directory + ); + } + + public function rm(string $file): array + { + return $this->client->request( + 'DELETE', + $this->baseUrl.'/'.$file + ); + } + + public function exists(string $file): bool + { + $response = $this->client->request('GET', $this->baseUrl.'/'.$file); + + return 404 !== $response['statusCode']; + } +} diff --git a/src/Controller/BillAdminController.php b/src/Controller/BillAdminController.php index f57f6b5..e68e00d 100644 --- a/src/Controller/BillAdminController.php +++ b/src/Controller/BillAdminController.php @@ -21,6 +21,8 @@ use Symfony\Component\Form\Form; use function Symfony\Component\String\u; use App\Repository\BillVendorRepositoryQuery; use App\Factory\BillVendorFactory; +use App\Repository\BillCategoryRepositoryQuery; +use App\Factory\BillCategoryFactory; class BillAdminController extends CrudController { @@ -71,6 +73,8 @@ class BillAdminController extends CrudController EntityManager $entityManager, BillVendorRepositoryQuery $vendorQuery, BillVendorFactory $vendorFactory, + BillCategoryRepositoryQuery $categoryQuery, + BillCategoryFactory $categoryFactory, Request $request ): Response { @@ -78,25 +82,39 @@ class BillAdminController extends CrudController $entity, $entityManager, $request, - function(Entity $entity, Form $form, Request $request) use ($entityManager, $vendorQuery, $vendorFactory) { - $vendor = $form->get('vendor')->getData(); - $customVendor = $form->get('customVendor')->getData(); + function(Entity $entity, Form $form, Request $request) use ( + $entityManager, + $vendorQuery, + $vendorFactory, + $categoryQuery, + $categoryFactory + ) { + foreach ([ + 'vendor' => [$vendorQuery, $vendorFactory, true], + 'category' => [$categoryQuery, $categoryFactory, false], + ] as $key => $elements) { + $value = $form->get($key)->getData(); + $customValue = $form->get(u('custom_'.$key)->camel())->getData(); - if ($customVendor !== null) { - $customVendor = u($customVendor)->upper(); - $vendor = $vendorQuery->create() - ->where('.label = :label') - ->setParameter(':label', $customVendor) - ->findOne() - ; + if ($customValue !== null) { + if ($elements[2]) { + $customValue = u($customValue)->upper(); + } - if ($vendor === null) { - $vendor = $vendorFactory->create($customVendor); - $entityManager->create($vendor); + $value = $elements[0]->create() + ->where('.label = :label') + ->setParameter(':label', $customValue) + ->findOne() + ; + + if ($value === null) { + $value = $elements[1]->create($customValue); + $entityManager->create($value); + } } - } - $entity->setVendor($vendor); + $entity->{(string) u('set_'.$key)->camel()}($value); + } } ); } @@ -178,6 +196,12 @@ class BillAdminController extends CrudController 'button_attr' => ['style' => 'user-select: all'], 'sort' => ['vendor', '.vendor'], ]) + ->setField('index', 'Catégorie', Field\ButtonField::class, [ + 'property' => 'category', + 'button_tag' => 'span', + 'button_attr' => ['style' => 'user-select: all'], + 'sort' => ['category', '.category'], + ]) ->setField('index', 'Date', Field\DateField::class, [ 'property' => 'date', 'sort' => ['date', '.date'], diff --git a/src/Controller/BillCategoryAdminController.php b/src/Controller/BillCategoryAdminController.php new file mode 100644 index 0000000..876b9cc --- /dev/null +++ b/src/Controller/BillCategoryAdminController.php @@ -0,0 +1,129 @@ + '\d+'])] + public function index(RepositoryQuery $query, Request $request, Session $session, int $page = 1): Response + { + return $this->doIndex($page, $query, $request, $session); + } + + #[Route(path: "/admin/bill_category/new", name: "admin_bill_category_new", methods: ['GET', 'POST'])] + public function new(Factory $factory, EntityManager $entityManager, Request $request): Response + { + return $this->doNew($factory->create(), $entityManager, $request); + } + + #[Route(path: "/admin/bill_category/show/{entity}", name: "admin_bill_category_show", methods: ['GET'])] + public function show(Entity $entity): Response + { + return $this->doShow($entity); + } + + #[Route(path: "/admin/bill_category/filter", name: "admin_bill_category_filter", methods: ['GET'])] + public function filter(Session $session): Response + { + return $this->doFilter($session); + } + + #[Route(path: "/admin/bill_category/edit/{entity}", name: "admin_bill_category_edit", methods: ['GET', 'POST'])] + public function edit(Entity $entity, EntityManager $entityManager, Request $request): Response + { + return $this->doEdit($entity, $entityManager, $request); + } + + #[Route(path: "/admin/bill_category/sort/{page}", name: "admin_bill_category_sort", methods: ['POST'], requirements: ['page' => '\d+'])] + public function sort(RepositoryQuery $query, EntityManager $entityManager, Request $request, Session $session, int $page = 1): Response + { + return $this->doSort($page, $query, $entityManager, $request, $session); + } + + #[Route(path: "/admin/bill_category/batch/{page}", name: "admin_bill_category_batch", methods: ['POST'], requirements: ['page' => '\d+'])] + public function batch(RepositoryQuery $query, EntityManager $entityManager, Request $request, Session $session, int $page = 1): Response + { + return $this->doBatch($page, $query, $entityManager, $request, $session); + } + + #[Route(path: "/admin/bill_category/delete/{entity}", name: "admin_bill_category_delete", methods: ['DELETE', 'POST'])] + public function delete(Entity $entity, EntityManager $entityManager, Request $request): Response + { + return $this->doDelete($entity, $entityManager, $request); + } + + protected function getConfiguration(): CrudConfiguration + { + return CrudConfiguration::create() + ->setPageTitle('index', 'Catégories des factures') + ->setPageTitle('edit', '{label}') + ->setPageTitle('new', 'Nouvelle catégorie') + ->setPageTitle('show', '{label}') + + ->setPageRoute('index', 'admin_bill_category_index') + ->setPageRoute('new', 'admin_bill_category_new') + ->setPageRoute('edit', 'admin_bill_category_edit') + ->setPageRoute('show', 'admin_bill_category_show') + ->setPageRoute('sort', 'admin_bill_category_sort') + ->setPageRoute('batch', 'admin_bill_category_batch') + ->setPageRoute('delete', 'admin_bill_category_delete') + ->setPageRoute('filter', 'admin_bill_category_filter') + + ->setForm('edit', Type::class, []) + ->setForm('new', Type::class) + // ->setForm('filter', Type::class) + + // ->setMaxPerPage('index', 20) + + // ->setIsSortableCollection('index', false) + // ->setSortableCollectionProperty('sortOrder') + + // ->setAction('index', 'new', true) + // ->setAction('index', 'show', true) + // ->setAction('index', 'edit', true) + // ->setAction('index', 'delete', true) + + // ->setAction('edit', 'back', true) + // ->setAction('edit', 'show', true) + // ->setAction('edit', 'delete', true) + + // ->setAction('show', 'back', true) + // ->setAction('show', 'edit', true) + + ->setDefaultSort('index', 'label', 'ASC') + ->setField('index', 'Libellé', Field\TextField::class, [ + 'property' => 'label', + 'sort' => ['label', '.label'], + ]) + + // ->setField('index', 'Foo', Field\TextField::class, [ + // 'property' => 'foo', + // ]) + + // ->setBatchAction('index', 'delete', 'Delete', function(EntityInterface $entity, EntityManager $manager) { + // $manager->delete($entity); + // }) + ; + } + + protected function getSection(): string + { + return 'bill_category'; + } +} diff --git a/src/Entity/Bill.php b/src/Entity/Bill.php index ffad52a..dc4c6e3 100644 --- a/src/Entity/Bill.php +++ b/src/Entity/Bill.php @@ -6,8 +6,10 @@ use App\Repository\BillRepository; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use App\Core\Entity\EntityInterface; +use App\Core\Doctrine\Timestampable; #[ORM\Entity(repositoryClass: BillRepository::class)] +#[ORM\HasLifecycleCallbacks] class Bill implements EntityInterface { #[ORM\Id] @@ -40,6 +42,12 @@ class Bill implements EntityInterface #[ORM\JoinColumn(onDelete: 'SET NULL')] private ?BillVendor $vendor = null; + #[ORM\ManyToOne(inversedBy: 'bills')] + #[ORM\JoinColumn(onDelete: 'SET NULL')] + private ?BillCategory $category = null; + + use Timestampable; + public function getId(): ?int { return $this->id; @@ -145,4 +153,47 @@ class Bill implements EntityInterface return $this; } + + public function getCategory(): ?BillCategory + { + return $this->category; + } + + public function setCategory(?BillCategory $category): self + { + $this->category = $category; + + return $this; + } + + public function isPdf(): bool + { + return (bool) preg_match('/\.pdf/', $this->getFile()); + } + + public function getRemoteFile(): ?string + { + if (!$this->getFile()) { + return null; + } + + if (!$this->getDate()) { + return null; + } + + if (!$this->getCategory()) { + return null; + } + + if (!$this->getVendor()) { + return null; + } + + return implode('/', [ + $this->getDate()->format('Y'), + $this->getCategory()->getLabel(), + $this->getVendor()->getLabel(), + basename($this->getFile()), + ]); + } } diff --git a/src/Entity/BillCategory.php b/src/Entity/BillCategory.php new file mode 100644 index 0000000..243367a --- /dev/null +++ b/src/Entity/BillCategory.php @@ -0,0 +1,85 @@ +bills = new ArrayCollection(); + } + + public function __toString() + { + return (string) $this->getLabel(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getLabel(): ?string + { + return $this->label; + } + + public function setLabel(string $label): self + { + $this->label = $label; + + return $this; + } + + /** + * @return Collection + */ + public function getBills(): Collection + { + return $this->bills; + } + + public function addBill(Bill $bill): self + { + if (!$this->bills->contains($bill)) { + $this->bills->add($bill); + $bill->setCategory($this); + } + + return $this; + } + + public function removeBill(Bill $bill): self + { + if ($this->bills->removeElement($bill)) { + // set the owning side to null (unless already changed) + if ($bill->getCategory() === $this) { + $bill->setCategory(null); + } + } + + return $this; + } +} diff --git a/src/Entity/BillVendor.php b/src/Entity/BillVendor.php index 7f63e6c..c4e0288 100644 --- a/src/Entity/BillVendor.php +++ b/src/Entity/BillVendor.php @@ -7,8 +7,10 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use App\Core\Entity\EntityInterface; +use App\Core\Doctrine\Timestampable; #[ORM\Entity(repositoryClass: BillVendorRepository::class)] +#[ORM\HasLifecycleCallbacks] class BillVendor implements EntityInterface { #[ORM\Id] @@ -22,6 +24,8 @@ class BillVendor implements EntityInterface #[ORM\OneToMany(mappedBy: 'vendor', targetEntity: Bill::class)] private Collection $bills; + use Timestampable; + public function __construct() { $this->bills = new ArrayCollection(); diff --git a/src/Factory/BillCategoryFactory.php b/src/Factory/BillCategoryFactory.php new file mode 100644 index 0000000..59bcd94 --- /dev/null +++ b/src/Factory/BillCategoryFactory.php @@ -0,0 +1,17 @@ +setLabel((string) $label); + + return $entity; + } +} diff --git a/src/Factory/BillVendorFactory.php b/src/Factory/BillVendorFactory.php index c9b6344..b22df7b 100644 --- a/src/Factory/BillVendorFactory.php +++ b/src/Factory/BillVendorFactory.php @@ -7,10 +7,10 @@ use App\Entity\BillVendor as Entity; class BillVendorFactory implements FactoryInterface { - public function create(string $label): Entity + public function create(?string $label = null): Entity { $entity = new Entity(); - $entity->setLabel($label); + $entity->setLabel((string) $label); return $entity; } diff --git a/src/Form/BillCategoryType.php b/src/Form/BillCategoryType.php new file mode 100644 index 0000000..dcd494c --- /dev/null +++ b/src/Form/BillCategoryType.php @@ -0,0 +1,25 @@ +add('label') + ; + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => BillCategory::class, + ]); + } +} diff --git a/src/Form/BillFilterType.php b/src/Form/BillFilterType.php index c0c8f9b..3f72768 100644 --- a/src/Form/BillFilterType.php +++ b/src/Form/BillFilterType.php @@ -15,6 +15,7 @@ use App\Entity\BillPeer; use Symfony\Bridge\Doctrine\Form\Type\EntityType; use App\Entity\BillVendor; use Doctrine\ORM\EntityRepository; +use App\Entity\BillCategory; class BillFilterType extends AbstractType { @@ -42,6 +43,19 @@ class BillFilterType extends AbstractType 'data-jschoice' => '', ], ]) + ->add('category', EntityType::class, [ + 'label' => 'Catégorie', + 'required' => false, + 'class' => BillCategory::class, + 'query_builder' => function (EntityRepository $er) { + return $er->createQueryBuilder('v') + ->orderBy('v.label', 'ASC') + ; + }, + 'attr' => [ + 'data-jschoice' => '', + ], + ]) ->add('status', ChoiceType::class, [ 'choices' => BillPeer::choices(), 'required' => false, diff --git a/src/Form/BillType.php b/src/Form/BillType.php index 4f0354e..475a82f 100644 --- a/src/Form/BillType.php +++ b/src/Form/BillType.php @@ -15,6 +15,7 @@ use Symfony\Component\Validator\Constraints\File; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Form\Extension\Core\Type\NumberType; use App\Entity\BillPeer; +use App\Entity\BillCategory; class BillType extends AbstractType { @@ -64,6 +65,30 @@ class BillType extends AbstractType 'required' => false, 'mapped' => false, ]) + ->add('category', EntityType::class, [ + 'label' => 'Catégorie', + 'required' => false, + 'class' => BillCategory::class, + 'label_attr' => [ + 'class' => 'mt-3', + ], + 'query_builder' => function (EntityRepository $er) { + return $er->createQueryBuilder('v') + ->orderBy('v.label', 'ASC') + ; + }, + 'attr' => [ + 'data-jschoice' => '', + ], + ]) + ->add('customCategory', null, [ + 'label' => 'Ajouter une catégorie', + 'label_attr' => [ + 'class' => 'font-weight-normal', + ], + 'required' => false, + 'mapped' => false, + ]) ->add('date', null, [ 'html5' => true, 'widget' => 'single_text', @@ -79,13 +104,21 @@ class BillType extends AbstractType ->add('amountTtc', NumberType::class, [ 'label' => 'Montant TTC', 'html5' => true, + 'scale' => 2, 'label_attr' => [ 'class' => 'mt-3', ], + 'attr' => [ + 'step' => 0.01, + ], ]) ->add('amountHt', NumberType::class, [ 'label' => 'Montant HT', + 'scale' => 2, 'html5' => true, + 'attr' => [ + 'step' => 0.01, + ], ]) ->add('status', ChoiceType::class, [ 'choices' => BillPeer::choices(), diff --git a/src/Repository/BillCategoryRepository.php b/src/Repository/BillCategoryRepository.php new file mode 100644 index 0000000..c9ae34b --- /dev/null +++ b/src/Repository/BillCategoryRepository.php @@ -0,0 +1,66 @@ + + * + * @method BillCategory|null find($id, $lockMode = null, $lockVersion = null) + * @method BillCategory|null findOneBy(array $criteria, array $orderBy = null) + * @method BillCategory[] findAll() + * @method BillCategory[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class BillCategoryRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, BillCategory::class); + } + + public function save(BillCategory $entity, bool $flush = false): void + { + $this->getEntityManager()->persist($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + + public function remove(BillCategory $entity, bool $flush = false): void + { + $this->getEntityManager()->remove($entity); + + if ($flush) { + $this->getEntityManager()->flush(); + } + } + +// /** +// * @return BillCategory[] Returns an array of BillCategory objects +// */ +// public function findByExampleField($value): array +// { +// return $this->createQueryBuilder('b') +// ->andWhere('b.exampleField = :val') +// ->setParameter('val', $value) +// ->orderBy('b.id', 'ASC') +// ->setMaxResults(10) +// ->getQuery() +// ->getResult() +// ; +// } + +// public function findOneBySomeField($value): ?BillCategory +// { +// return $this->createQueryBuilder('b') +// ->andWhere('b.exampleField = :val') +// ->setParameter('val', $value) +// ->getQuery() +// ->getOneOrNullResult() +// ; +// } +} diff --git a/src/Repository/BillCategoryRepositoryQuery.php b/src/Repository/BillCategoryRepositoryQuery.php new file mode 100644 index 0000000..9bdd782 --- /dev/null +++ b/src/Repository/BillCategoryRepositoryQuery.php @@ -0,0 +1,15 @@ + -
+
{% for item in form %} {% if configuration.isI18n and item.vars.name == 'translations' %} {% include(configuration.view('form_translations', '@Core/admin/crud/_form_translations.html.twig')) with {form: item} %} @@ -9,9 +9,20 @@ {% endif %} {% endfor %}
-
- +
+ {% if entity.isPdf %} +
+ {% else %} +
+
+
+ + + +
+
+
+ {% endif %}
{% else %} diff --git a/templates/admin/bill/_show.html.twig b/templates/admin/bill/_show.html.twig index 47e643f..7af5fae 100644 --- a/templates/admin/bill/_show.html.twig +++ b/templates/admin/bill/_show.html.twig @@ -1,6 +1,7 @@ {% set values = { 'Référence': entity.reference, 'Fournisseur': entity.vendor, + 'Catégorie': entity.category, 'Montant TTC': entity.amountTtc is not null ? (entity.amountTtc|number_format(2, ',') ~ ' €') : '/', 'Montant HT': entity.amountHt is not null ? (entity.amountHt|number_format(2, ',') ~ ' €') : '/', 'Status': entity.humanStatus, @@ -19,8 +20,19 @@
- + {% if entity.isPdf %} +
+ {% else %} +
+
+
+ + + +
+
+
+ {% endif %}
diff --git a/templates/admin/menu.html.twig b/templates/admin/menu.html.twig index 88aaff4..0d9d8ab 100644 --- a/templates/admin/menu.html.twig +++ b/templates/admin/menu.html.twig @@ -66,19 +66,28 @@ {{ include('@Core/admin/module/_menu_section.html.twig', {label: 'Comptabilité'}) }}