Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/config/packages/backoffice_menu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ parameters:
niveau: 'ROLE_ADMIN'
extra_routes:
- admin_accounting_invoices_list
- admin_accounting_invoices_edit
compta_journal:
nom: 'Journal'
url: '/admin/accounting/journal/list'
Expand Down
4 changes: 4 additions & 0 deletions app/config/routing/admin_accounting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ admin_accounting_invoices_list:
path: /invoices/list
defaults: {_controller: AppBundle\Controller\Admin\Accounting\Invoice\ListInvoiceAction}

admin_accounting_invoices_edit:
Comment thread
vgreb marked this conversation as resolved.
path: /invoices/edit
defaults: {_controller: AppBundle\Controller\Admin\Accounting\Invoice\EditInvoiceAction}

admin_accounting_invoices_download:
path: /invoices/download
defaults: {_controller: AppBundle\Controller\Admin\Accounting\Invoice\DownloadInvoiceAction}
Expand Down
149 changes: 149 additions & 0 deletions sources/AppBundle/Accounting/Form/InvoiceType.php
Comment thread
vgreb marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<?php

declare(strict_types=1);

namespace AppBundle\Accounting\Form;

use Afup\Site\Utils\Pays;
use AppBundle\Accounting\InvoicingCurrency;
use AppBundle\Accounting\InvoicingPaymentStatus;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\EnumType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints as Assert;

class InvoiceType extends AbstractType
{
public function __construct(private readonly Pays $pays) {}

public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('invoiceDate', DateType::class, [
'label' => 'Date facture',
'widget' => 'single_text',
])->add('company', TextType::class, [
'label' => 'Société',
'constraints' => [
new Assert\NotBlank(),
new Assert\Length(max: 50),
],
])->add('service', TextType::class, [
'label' => 'Service',
'required' => false,
'constraints' => [
new Assert\Length(max: 50),
],
])->add('address', TextareaType::class, [
'label' => 'Adresse',
])->add('zipcode', TextType::class, [
'label' => 'Code postal',
'constraints' => [
new Assert\NotBlank(),
new Assert\Length(max: 10),
],
])->add('city', TextType::class, [
'label' => 'Ville',
'constraints' => [
new Assert\NotBlank(),
new Assert\Length(max: 50),
],
])->add('countryId', ChoiceType::class, [
'label' => 'Pays',
'choices' => array_flip($this->pays->obtenirPays()),
])->add('lastname', TextType::class, [
'label' => 'Nom',
'required' => false,
'constraints' => [
new Assert\Length(max: 50),
],
])->add('firstname', TextType::class, [
'label' => 'Prénom',
'required' => false,
'constraints' => [
new Assert\Length(max: 50),
],
])->add('phone', TextType::class, [
'label' => 'Tel',
'required' => false,
'constraints' => [
new Assert\Length(max: 30),
],
])->add('email', EmailType::class, [
'label' => 'Email (facture)',
'constraints' => [
new Assert\NotBlank(),
new Assert\Length(max: 100),
],
])->add('tvaIntra', TextType::class, [
'label' => 'TVA intracommunautaire (facture)',
'required' => false,
'constraints' => [
new Assert\Length(max: 20),
],
])->add('refClt1', TextType::class, [
'label' => 'Référence client',
'required' => false,
'constraints' => [
new Assert\Length(max: 50),
],
])->add('refClt2', TextType::class, [
'label' => 'Référence client 2',
'required' => false,
'constraints' => [
new Assert\Length(max: 50),
],
])->add('refClt3', TextType::class, [
'label' => 'Référence client 3',
'required' => false,
'constraints' => [
new Assert\Length(max: 50),
],
])->add('observation', TextareaType::class, [
'required' => false,
'label' => 'Observation',
])->add('currency', EnumType::class, [
'required' => false,
'class' => InvoicingCurrency::class,
'attr' => ['size' => count(InvoicingCurrency::cases())],
'label' => 'Monnaie de la facture',
'placeholder' => false,
])->add('details', CollectionType::class, [
'entry_type' => InvoicingRowType::class,
'keep_as_list' => true,
'allow_add' => false,
'allow_delete' => false,
])->add('quotationNumber', TextType::class, [
'label' => 'Numéro de devis',
'required' => false,
'attr' => ['readonly' => 'readonly'],
'constraints' => [
new Assert\Length(max: 50),
],
])->add('invoiceNumber', TextType::class, [
'label' => 'Numéro facture',
'required' => false,
'attr' => ['readonly' => 'readonly'],
'constraints' => [
new Assert\Length(max: 50),
],
])->add('paymentStatus', EnumType::class, [
'required' => false,
'class' => InvoicingPaymentStatus::class,
'attr' => ['size' => count(InvoicingPaymentStatus::cases())],
'label' => 'État paiement',
'placeholder' => false,
'choice_label' => fn(InvoicingPaymentStatus $choice, string $key, mixed $value): string => $choice->label(),
])
->add('paymentDate', DateType::class, [
'label' => 'Date de paiement',
'required' => false,
'widget' => 'single_text',
]);
}
}
9 changes: 9 additions & 0 deletions sources/AppBundle/Accounting/InvoicingPaymentStatus.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,13 @@ enum InvoicingPaymentStatus: int
case Waiting = 0;
case Payed = 1;
case Cancelled = 2;

public function label(): string
{
return match ($this) {
self::Waiting => 'En attente de paiement',
self::Payed => 'Payé',
self::Cancelled => 'Annulé',
};
}
}
7 changes: 4 additions & 3 deletions sources/AppBundle/Accounting/Model/Invoicing.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Afup\Site\Utils\Utils;
use AppBundle\Accounting\InvoicingCurrency;
use AppBundle\Accounting\InvoicingPaymentStatus;
use CCMBenchmark\Ting\Entity\NotifyProperty;
use CCMBenchmark\Ting\Entity\NotifyPropertyInterface;
use DateTime;
Expand Down Expand Up @@ -34,7 +35,7 @@ class Invoicing implements NotifyPropertyInterface
private string $lastname = '';
private string $firstname = '';
private string $phone = '';
private int $paymentStatus = 0;
private InvoicingPaymentStatus $paymentStatus = InvoicingPaymentStatus::Waiting;
private ?DateTime $paymentDate = null;
private ?InvoicingCurrency $currency = null;
/** @var InvoicingDetail[] */
Expand Down Expand Up @@ -301,12 +302,12 @@ public function setPhone(string $phone): self
return $this;
}

public function getPaymentStatus(): int
public function getPaymentStatus(): InvoicingPaymentStatus
{
return $this->paymentStatus;
}

public function setPaymentStatus(int $paymentStatus): self
public function setPaymentStatus(InvoicingPaymentStatus $paymentStatus): self
{
$this->propertyChanged('paymentStatus', $this->paymentStatus, $paymentStatus);
$this->paymentStatus = $paymentStatus;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace AppBundle\Accounting\Model\Repository;

use AppBundle\Accounting\InvoicingPaymentStatus;
use CCMBenchmark\Ting\Repository\Hydrator\AggregateFrom;
use CCMBenchmark\Ting\Repository\Hydrator\AggregateTo;
use CCMBenchmark\Ting\Repository\Hydrator\RelationMany;
Expand All @@ -25,21 +26,21 @@
*/
class InvoicingRepository extends Repository implements MetadataInitializer
{
public function getQuotationById(int $periodId): ?Invoicing
public function getById(int $id): ?Invoicing
{
/** @var Select $builder */
$builder = $this->getQueryBuilder(self::QUERY_SELECT);
$builder->cols(['acf.*', 'acfd.*'])
->from('afup_compta_facture acf')
->leftJoin('afup_compta_facture_details acfd', 'acfd.idafup_compta_facture = acf.id')
->where('acf.id = :periodId');
->where('acf.id = :id');

$hydrator = new HydratorRelational();
$hydrator->addRelation(new RelationMany(new AggregateFrom('acfd'), new AggregateTo('acf'), 'setDetails'));
$hydrator->callableFinalizeAggregate(fn(array $row) => $row['acf']);

$collection = $this->getQuery($builder->getStatement())
->setParams(['periodId' => $periodId])
->setParams(['id' => $id])
->query($this->getCollection($hydrator));

if ($collection->count() === 0) {
Expand Down Expand Up @@ -240,7 +241,11 @@ public static function initMetadata(SerializerFactoryInterface $serializerFactor
->addField([
'columnName' => 'etat_paiement',
'fieldName' => 'paymentStatus',
'type' => 'int',
'type' => 'enum',
'serializer' => BackedEnum::class,
'serializer_options' => [
'unserialize' => ['enum' => InvoicingPaymentStatus::class],
],
])
->addField([
'columnName' => 'date_paiement',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types=1);

namespace AppBundle\Controller\Admin\Accounting\Invoice;

use AppBundle\Accounting\Form\InvoiceType;
use AppBundle\Accounting\Model\Invoicing;
use AppBundle\Accounting\Model\Repository\InvoicingDetailRepository;
use AppBundle\Accounting\Model\Repository\InvoicingRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class EditInvoiceAction extends AbstractController
{
public function __construct(
private readonly InvoicingRepository $invoicingRepository,
private readonly InvoicingDetailRepository $invoicingDetailRepository,
) {}

public function __invoke(Request $request): Response
{
$invoiceId = $request->query->getInt('invoiceId');
$invoice = $this->invoicingRepository->getById($invoiceId);
if (!$invoice instanceof Invoicing) {
throw $this->createNotFoundException("Cette facture n'existe pas");
}

$form = $this->createForm(InvoiceType::class, $invoice);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
try {
$this->invoicingRepository->startTransaction();
$keepIds = array_filter(array_map(fn($d) => $d->getId(), $invoice->getDetails()));
$existingIds = $this->invoicingDetailRepository->getRowsIdsPerInvoicingId($invoiceId);
$toDelete = array_diff($existingIds, $keepIds);
if ($toDelete !== []) {
$this->invoicingDetailRepository->removeRowsPerIds($toDelete);
}
foreach ($invoice->getDetails() as $detail) {
$this->invoicingDetailRepository->save($detail);
}
$this->invoicingRepository->save($invoice);
$this->invoicingRepository->commit();
$this->addFlash('success', 'L\'écriture a été modifiée');
return $this->redirectToRoute('admin_accounting_invoices_list');
} catch (\Exception $e) {
$this->invoicingRepository->rollback();
$this->addFlash('error', 'L\'écriture n\'a pas pu être enregistrée');
}
}

return $this->render('admin/accounting/invoice/edit.html.twig', [
'invoice' => $invoice,
'form' => $form->createView(),
'submitLabel' => 'Modifier',
]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public function __invoke(Request $request): Response

/** @var Invoicing $invoice */
foreach ($invoices as $invoice) {
if ($invoice->getPaymentStatus() === InvoicingPaymentStatus::Cancelled->value) {
if ($invoice->getPaymentStatus() === InvoicingPaymentStatus::Cancelled) {
continue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public function __invoke(Request $request): Response

private function init(int $quotationId): Invoicing
{
$baseQuotation = $this->invoicingRepository->getQuotationById($quotationId);
$baseQuotation = $this->invoicingRepository->getById($quotationId);
if (!$baseQuotation instanceof Invoicing) {
$quotation = new Invoicing();
$quotation->setQuotationDate(new \DateTime());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
public function __invoke(Request $request): Response
{
$quotationId = $request->query->getInt('quotationId');
$quotation = $this->invoicingRepository->getQuotationById($quotationId);
$quotation = $this->invoicingRepository->getById($quotationId);
if ($quotation === null) {
throw $this->createNotFoundException("Ce devis n'existe pas");
}
Expand Down
Loading
Loading