Skip to content

Commit 4837d28

Browse files
committed
Refonte Trésorie > Facture - Ajout / Edition
1 parent b153f9f commit 4837d28

16 files changed

Lines changed: 423 additions & 19 deletions

File tree

app/config/packages/backoffice_menu.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ parameters:
236236
niveau: 'ROLE_ADMIN'
237237
extra_routes:
238238
- admin_accounting_invoices_list
239+
- admin_accounting_invoices_edit
239240
compta_journal:
240241
nom: 'Journal'
241242
url: '/admin/accounting/journal/list'

app/config/routing/admin_accounting.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ admin_accounting_invoices_list:
3434
path: /invoices/list
3535
defaults: {_controller: AppBundle\Controller\Admin\Accounting\Invoice\ListInvoiceAction}
3636

37+
admin_accounting_invoices_edit:
38+
path: /invoices/edit
39+
defaults: {_controller: AppBundle\Controller\Admin\Accounting\Invoice\EditInvoiceAction}
40+
3741
admin_accounting_invoices_download:
3842
path: /invoices/download
3943
defaults: {_controller: AppBundle\Controller\Admin\Accounting\Invoice\DownloadInvoiceAction}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace AppBundle\Accounting\Form;
6+
7+
use Afup\Site\Utils\Pays;
8+
use AppBundle\Accounting\InvoicingCurrency;
9+
use AppBundle\Accounting\InvoicingPaymentStatus;
10+
use Symfony\Component\Form\AbstractType;
11+
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
12+
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
13+
use Symfony\Component\Form\Extension\Core\Type\DateType;
14+
use Symfony\Component\Form\Extension\Core\Type\EmailType;
15+
use Symfony\Component\Form\Extension\Core\Type\EnumType;
16+
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
17+
use Symfony\Component\Form\Extension\Core\Type\TextType;
18+
use Symfony\Component\Form\FormBuilderInterface;
19+
use Symfony\Component\Validator\Constraints as Assert;
20+
21+
class InvoiceType extends AbstractType
22+
{
23+
public function __construct(private readonly Pays $pays) {}
24+
25+
public function buildForm(FormBuilderInterface $builder, array $options): void
26+
{
27+
$builder->add('invoiceDate', DateType::class, [
28+
'label' => 'Date facture',
29+
'widget' => 'single_text',
30+
])->add('company', TextType::class, [
31+
'label' => 'Société',
32+
'constraints' => [
33+
new Assert\NotBlank(),
34+
new Assert\Length(max: 50),
35+
],
36+
])->add('service', TextType::class, [
37+
'label' => 'Service',
38+
'required' => false,
39+
'empty_data' => '',
40+
'constraints' => [
41+
new Assert\Length(max: 50),
42+
],
43+
])->add('address', TextareaType::class, [
44+
'label' => 'Adresse',
45+
])->add('zipcode', TextType::class, [
46+
'label' => 'Code postal',
47+
'constraints' => [
48+
new Assert\NotBlank(),
49+
new Assert\Length(max: 10),
50+
],
51+
])->add('city', TextType::class, [
52+
'label' => 'Ville',
53+
'constraints' => [
54+
new Assert\NotBlank(),
55+
new Assert\Length(max: 50),
56+
],
57+
])->add('countryId', ChoiceType::class, [
58+
'label' => 'Pays',
59+
'choices' => array_flip($this->pays->obtenirPays()),
60+
])->add('lastname', TextType::class, [
61+
'label' => 'Nom',
62+
'required' => false,
63+
'empty_data' => '',
64+
'constraints' => [
65+
new Assert\Length(max: 50),
66+
],
67+
])->add('firstname', TextType::class, [
68+
'label' => 'Prénom',
69+
'required' => false,
70+
'empty_data' => '',
71+
'constraints' => [
72+
new Assert\Length(max: 50),
73+
],
74+
])->add('phone', TextType::class, [
75+
'label' => 'Tel',
76+
'required' => false,
77+
'empty_data' => '',
78+
'constraints' => [
79+
new Assert\Length(max: 30),
80+
],
81+
])->add('email', EmailType::class, [
82+
'label' => 'Email (facture)',
83+
'constraints' => [
84+
new Assert\NotBlank(),
85+
new Assert\Length(max: 100),
86+
],
87+
])->add('tvaIntra', TextType::class, [
88+
'label' => 'TVA intracommunautaire (facture)',
89+
'required' => false,
90+
'constraints' => [
91+
new Assert\Length(max: 20),
92+
],
93+
])->add('refClt1', TextType::class, [
94+
'label' => 'Référence client',
95+
'required' => false,
96+
'empty_data' => '',
97+
'constraints' => [
98+
new Assert\Length(max: 50),
99+
],
100+
])->add('refClt2', TextType::class, [
101+
'label' => 'Référence client 2',
102+
'required' => false,
103+
'empty_data' => '',
104+
'constraints' => [
105+
new Assert\Length(max: 50),
106+
],
107+
])->add('refClt3', TextType::class, [
108+
'label' => 'Référence client 3',
109+
'required' => false,
110+
'empty_data' => '',
111+
'constraints' => [
112+
new Assert\Length(max: 50),
113+
],
114+
])->add('observation', TextareaType::class, [
115+
'required' => false,
116+
'empty_data' => '',
117+
'label' => 'Observation',
118+
])->add('currency', EnumType::class, [
119+
'required' => false,
120+
'class' => InvoicingCurrency::class,
121+
'attr' => ['size' => count(InvoicingCurrency::cases())],
122+
'label' => 'Monnaie de la facture',
123+
'placeholder' => false,
124+
])->add('details', CollectionType::class, [
125+
'entry_type' => InvoicingRowType::class,
126+
'keep_as_list' => true,
127+
'allow_add' => false,
128+
'allow_delete' => false,
129+
'entry_options' => ['disabled' => true],
130+
])->add('quotationNumber', TextType::class, [
131+
'label' => 'Numéro de devis',
132+
'required' => false,
133+
'attr' => ['readonly' => 'readonly'],
134+
'constraints' => [
135+
new Assert\Length(max: 50),
136+
],
137+
])->add('invoiceNumber', TextType::class, [
138+
'label' => 'Numéro facture',
139+
'required' => false,
140+
'attr' => ['readonly' => 'readonly'],
141+
'constraints' => [
142+
new Assert\Length(max: 50),
143+
],
144+
])->add('paymentStatus', EnumType::class, [
145+
'required' => false,
146+
'class' => InvoicingPaymentStatus::class,
147+
'attr' => ['size' => count(InvoicingPaymentStatus::cases())],
148+
'label' => 'État paiement',
149+
'placeholder' => false,
150+
'choice_label' => fn(InvoicingPaymentStatus $choice, string $key, mixed $value): string => $choice->label(),
151+
])
152+
->add('paymentDate', DateType::class, [
153+
'label' => 'Date de paiement',
154+
'required' => false,
155+
'widget' => 'single_text',
156+
]);
157+
}
158+
}

sources/AppBundle/Accounting/InvoicingPaymentStatus.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,13 @@ enum InvoicingPaymentStatus: int
99
case Waiting = 0;
1010
case Payed = 1;
1111
case Cancelled = 2;
12+
13+
public function label(): string
14+
{
15+
return match ($this) {
16+
self::Waiting => 'En attente de paiement',
17+
self::Payed => 'Payé',
18+
self::Cancelled => 'Annulé',
19+
};
20+
}
1221
}

sources/AppBundle/Accounting/Model/Invoicing.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Afup\Site\Utils\Utils;
88
use AppBundle\Accounting\InvoicingCurrency;
9+
use AppBundle\Accounting\InvoicingPaymentStatus;
910
use CCMBenchmark\Ting\Entity\NotifyProperty;
1011
use CCMBenchmark\Ting\Entity\NotifyPropertyInterface;
1112
use DateTime;
@@ -34,7 +35,7 @@ class Invoicing implements NotifyPropertyInterface
3435
private string $lastname = '';
3536
private string $firstname = '';
3637
private string $phone = '';
37-
private int $paymentStatus = 0;
38+
private InvoicingPaymentStatus $paymentStatus = InvoicingPaymentStatus::Waiting;
3839
private ?DateTime $paymentDate = null;
3940
private ?InvoicingCurrency $currency = null;
4041
/** @var InvoicingDetail[] */
@@ -301,12 +302,12 @@ public function setPhone(string $phone): self
301302
return $this;
302303
}
303304

304-
public function getPaymentStatus(): int
305+
public function getPaymentStatus(): InvoicingPaymentStatus
305306
{
306307
return $this->paymentStatus;
307308
}
308309

309-
public function setPaymentStatus(int $paymentStatus): self
310+
public function setPaymentStatus(InvoicingPaymentStatus $paymentStatus): self
310311
{
311312
$this->propertyChanged('paymentStatus', $this->paymentStatus, $paymentStatus);
312313
$this->paymentStatus = $paymentStatus;

sources/AppBundle/Accounting/Model/Repository/InvoicingRepository.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace AppBundle\Accounting\Model\Repository;
66

7+
use AppBundle\Accounting\InvoicingPaymentStatus;
78
use CCMBenchmark\Ting\Repository\Hydrator\AggregateFrom;
89
use CCMBenchmark\Ting\Repository\Hydrator\AggregateTo;
910
use CCMBenchmark\Ting\Repository\Hydrator\RelationMany;
@@ -25,21 +26,21 @@
2526
*/
2627
class InvoicingRepository extends Repository implements MetadataInitializer
2728
{
28-
public function getQuotationById(int $periodId): ?Invoicing
29+
public function getById(int $id): ?Invoicing
2930
{
3031
/** @var Select $builder */
3132
$builder = $this->getQueryBuilder(self::QUERY_SELECT);
3233
$builder->cols(['acf.*', 'acfd.*'])
3334
->from('afup_compta_facture acf')
3435
->leftJoin('afup_compta_facture_details acfd', 'acfd.idafup_compta_facture = acf.id')
35-
->where('acf.id = :periodId');
36+
->where('acf.id = :id');
3637

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

4142
$collection = $this->getQuery($builder->getStatement())
42-
->setParams(['periodId' => $periodId])
43+
->setParams(['id' => $id])
4344
->query($this->getCollection($hydrator));
4445

4546
if ($collection->count() === 0) {
@@ -240,7 +241,11 @@ public static function initMetadata(SerializerFactoryInterface $serializerFactor
240241
->addField([
241242
'columnName' => 'etat_paiement',
242243
'fieldName' => 'paymentStatus',
243-
'type' => 'int',
244+
'type' => 'enum',
245+
'serializer' => BackedEnum::class,
246+
'serializer_options' => [
247+
'unserialize' => ['enum' => InvoicingPaymentStatus::class],
248+
],
244249
])
245250
->addField([
246251
'columnName' => 'date_paiement',
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace AppBundle\Controller\Admin\Accounting\Invoice;
6+
7+
use AppBundle\Accounting\Form\InvoiceType;
8+
use AppBundle\Accounting\Model\Invoicing;
9+
use AppBundle\Accounting\Model\Repository\InvoicingRepository;
10+
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
11+
use Symfony\Component\HttpFoundation\Request;
12+
use Symfony\Component\HttpFoundation\Response;
13+
14+
class EditInvoiceAction extends AbstractController
15+
{
16+
public function __construct(
17+
private readonly InvoicingRepository $invoicingRepository,
18+
) {}
19+
20+
public function __invoke(Request $request): Response
21+
{
22+
$invoiceId = $request->query->getInt('invoiceId');
23+
$invoice = $this->invoicingRepository->getById($invoiceId);
24+
if (!$invoice instanceof Invoicing) {
25+
throw $this->createNotFoundException("Cette facture n'existe pas");
26+
}
27+
28+
$form = $this->createForm(InvoiceType::class, $invoice);
29+
$form->handleRequest($request);
30+
if ($form->isSubmitted() && $form->isValid()) {
31+
try {
32+
$this->invoicingRepository->save($invoice);
33+
$this->addFlash('success', 'L\'écriture a été modifiée');
34+
return $this->redirectToRoute('admin_accounting_invoices_list');
35+
} catch (\Exception $e) {
36+
$this->invoicingRepository->rollback();
37+
$this->addFlash('error', 'L\'écriture n\'a pas pu être enregistrée');
38+
}
39+
}
40+
41+
return $this->render('admin/accounting/invoice/edit.html.twig', [
42+
'invoice' => $invoice,
43+
'form' => $form->createView(),
44+
'submitLabel' => 'Modifier',
45+
]);
46+
}
47+
}

sources/AppBundle/Controller/Admin/Accounting/Invoice/ListInvoiceAction.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public function __invoke(Request $request): Response
3838

3939
/** @var Invoicing $invoice */
4040
foreach ($invoices as $invoice) {
41-
if ($invoice->getPaymentStatus() === InvoicingPaymentStatus::Cancelled->value) {
41+
if ($invoice->getPaymentStatus() === InvoicingPaymentStatus::Cancelled) {
4242
continue;
4343
}
4444

sources/AppBundle/Controller/Admin/Accounting/Quotation/AddQuotationAction.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public function __invoke(Request $request): Response
5454

5555
private function init(int $quotationId): Invoicing
5656
{
57-
$baseQuotation = $this->invoicingRepository->getQuotationById($quotationId);
57+
$baseQuotation = $this->invoicingRepository->getById($quotationId);
5858
if (!$baseQuotation instanceof Invoicing) {
5959
$quotation = new Invoicing();
6060
$quotation->setQuotationDate(new \DateTime());

sources/AppBundle/Controller/Admin/Accounting/Quotation/EditQuotationAction.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public function __construct(
2121
public function __invoke(Request $request): Response
2222
{
2323
$quotationId = $request->query->getInt('quotationId');
24-
$quotation = $this->invoicingRepository->getQuotationById($quotationId);
24+
$quotation = $this->invoicingRepository->getById($quotationId);
2525
if ($quotation === null) {
2626
throw $this->createNotFoundException("Ce devis n'existe pas");
2727
}

0 commit comments

Comments
 (0)