diff --git a/src/Controller/Dashboard/FlowController.php b/src/Controller/Dashboard/FlowController.php index 2d15096..a9cb1d3 100644 --- a/src/Controller/Dashboard/FlowController.php +++ b/src/Controller/Dashboard/FlowController.php @@ -24,15 +24,12 @@ use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Routing\Attribute\Route; -use Symfony\Contracts\HttpClient\HttpClientInterface; - #[Route('/crm/flow')] class FlowController extends AbstractController { public function __construct( private readonly AppLogger $appLogger, private readonly OrderSessionRepository $orderSessionRepository, - private readonly HttpClientInterface $client, private readonly DevisRepository $devisRepository, private readonly ProductRepository $productRepository, private readonly OptionsRepository $optionsRepository, @@ -65,12 +62,6 @@ class FlowController extends AbstractController { $this->appLogger->record('VIEW', 'Consultation détails réservation en ligne #' . $session->getId()); - // Auto-calculation of delivery if missing or geometry missing - if (($session->getDeliveryDistance() === null || $session->getDeliveryPrice() === null || $session->getDeliveryGeometry() === null) && $session->getAdressEvent()) { - $this->calculateDelivery($session); - $em->flush(); - } - return $this->render('dashboard/flow/view.twig', [ 'session' => $session, 'prestataires' => $this->prestaireRepository->findAll(), @@ -80,12 +71,6 @@ class FlowController extends AbstractController #[Route('/update/{id}', name: 'app_crm_flow_update', methods: ['POST'])] public function update(\App\Entity\OrderSession $session, Request $request, \Doctrine\ORM\EntityManagerInterface $em): Response { - if ($request->request->has('deliveryDistance')) { - $session->setDeliveryDistance((float)$request->request->get('deliveryDistance')); - } - if ($request->request->has('deliveryPrice')) { - $session->setDeliveryPrice((float)$request->request->get('deliveryPrice')); - } if ($request->request->has('typePaiement')) { $session->setTypePaiement($request->request->get('typePaiement')); } @@ -142,8 +127,6 @@ class FlowController extends AbstractController $devis->setCustomer($session->getCustomer()); // 2.1 Set additional Devis fields from OrderSession - $devis->setDistance($session->getDeliveryDistance()); - $devis->setPriceShip($session->getDeliveryPrice()); $devis->setPaymentMethod($session->getTypePaiement()); $devis->setOrderSession($session); @@ -248,18 +231,6 @@ class FlowController extends AbstractController } } - // 7. Delivery Fee - if ($session->getDeliveryPrice() > 0) { - $devisOpt = new DevisOptions(); - $devisOpt->setOption("Frais de livraison"); - $dist = number_format($session->getDeliveryDistance(), 1, ',', ' '); - $town = $session->getBillingTown() ?: 'Ville inconnue'; - $devisOpt->setDetails("Livraison ($dist km) - $town"); - $devisOpt->setPriceHt($session->getDeliveryPrice()); - $em->persist($devisOpt); - $devis->addDevisOption($devisOpt); - } - // 1. DocuSeal (Version pour signature) $docusealService = new DevisPdfService($this->kernel, $devis, $this->productRepository, true); $this->savePdfFile($devis, $docusealService->generate(), 'dc_', 'setDevisDocuSealFile'); @@ -286,68 +257,6 @@ class FlowController extends AbstractController return $this->redirectToRoute('app_crm_flow'); } - private function calculateDelivery(\App\Entity\OrderSession $session): void - { - if (!$session->getAdressEvent() || !$session->getZipCodeEvent() || !$session->getTownEvent()) { - return; - } - - $query = sprintf('%s %s %s', $session->getAdressEvent(), $session->getZipCodeEvent(), $session->getTownEvent()); - - try { - $response = $this->client->request('GET', 'https://api-adresse.data.gouv.fr/search/', [ - 'query' => [ - 'q' => $query, - 'limit' => 1 - ] - ]); - - $content = $response->toArray(); - - if (!empty($content['features'])) { - $coords = $content['features'][0]['geometry']['coordinates']; - $lon = $coords[0]; - $lat = $coords[1]; - - // Point de départ (LudikEvent) - $startLat = 49.849; - $startLon = 3.286; - - // Calcul itinéraire via API Geoplateforme - $itineraireResponse = $this->client->request('GET', 'https://data.geopf.fr/navigation/itineraire', [ - 'query' => [ - 'resource' => 'bdtopo-osrm', - 'start' => $startLon . ',' . $startLat, - 'end' => $lon . ',' . $lat, - 'profile' => 'car', - 'optimization' => 'fastest', - 'distanceUnit' => 'kilometer', - 'geometryFormat' => 'geojson' - ] - ]); - - $itineraire = $itineraireResponse->toArray(); - $distance = $itineraire['distance']; - $geometry = $itineraire['geometry'] ?? null; - - $rate = 0.50; - $trips = 4; - $price = 0.0; - - if ($distance > 10) { - $chargedDistance = $distance - 10; - $price = ($chargedDistance * $trips) * $rate; - } - - $session->setDeliveryDistance($distance); - $session->setDeliveryPrice($price); - $session->setDeliveryGeometry($geometry); - } - } catch (\Exception $e) { - // Log error or silent fail - } - } - private function savePdfFile(Devis $devis, string $content, string $prefix, string $setterMethod): void { $tmpPath = sys_get_temp_dir() . '/' . $prefix . uniqid() . '.pdf'; diff --git a/src/Controller/ReserverController.php b/src/Controller/ReserverController.php index 1f77bcf..edaf0d7 100644 --- a/src/Controller/ReserverController.php +++ b/src/Controller/ReserverController.php @@ -38,7 +38,6 @@ use App\Service\Pdf\DevisPdfService; use App\Entity\Devis; use App\Entity\DevisLine; use App\Entity\CustomerAddress; -use Symfony\Contracts\HttpClient\HttpClientInterface; class ReserverController extends AbstractController { @@ -575,7 +574,6 @@ class ReserverController extends AbstractController ProductReserveRepository $productReserveRepository, EntityManagerInterface $em, OptionsRepository $optionsRepository, - HttpClientInterface $client, Request $request, Mailer $mailer ): Response { @@ -644,14 +642,6 @@ class ReserverController extends AbstractController $cartData = $this->buildCartData($products, $selectedOptionsMap, $duration, $optionsRepository, $uploaderHelper, $promotion, $formule); - // --- Calcul Frais de Livraison --- - $deliveryData = $this->calculateDelivery( - $session->getAdressEvent(), - $session->getZipCodeEvent(), - $session->getTownEvent(), - $client - ); - return $this->render('revervation/flow_confirmed.twig', [ 'session' => $session, 'cart' => [ @@ -668,7 +658,6 @@ class ReserverController extends AbstractController 'formule' => $cartData['total']['formule'], 'tvaEnabled' => $cartData['tvaEnabled'], ], - 'delivery' => $deliveryData ]); } @@ -1191,40 +1180,6 @@ class ReserverController extends AbstractController return $this->render('revervation/hosting.twig'); } - #[Route('/estimer-la-livraison', name: 'reservation_estimate_delivery')] - public function estimateDelivery(Request $request, HttpClientInterface $client): Response - { - $form = $this->createFormBuilder() - ->add('address', TextType::class, ['required' => true]) - ->add('zipCode', TextType::class, ['required' => true]) - ->add('city', TextType::class, ['required' => true]) - ->getForm(); - - $form->handleRequest($request); - $estimation = null; - $details = null; - $geometry = null; - - if ($form->isSubmitted() && $form->isValid()) { - $data = $form->getData(); - $deliveryData = $this->calculateDelivery($data['address'], $data['zipCode'], $data['city'], $client); - - if ($deliveryData['details'] !== null) { - $estimation = $deliveryData['estimation']; - $details = $deliveryData['details']; - $geometry = $deliveryData['geometry']; - } else { - $this->addFlash('warning', 'Adresse introuvable ou erreur lors du calcul.'); - } - } - - return $this->render('revervation/estimate_delivery.twig', [ - 'form' => $form->createView(), - 'estimation' => $estimation, - 'details' => $details, - 'geometry' => $geometry - ]); - } // --- Private Helper Methods --- @@ -1265,80 +1220,6 @@ class ReserverController extends AbstractController return isset($_ENV['TVA_ENABLED']) && $_ENV['TVA_ENABLED'] === "true"; } - private function calculateDelivery(?string $address, ?string $zipCode, ?string $town, HttpClientInterface $client): array - { - $result = [ - 'estimation' => null, - 'details' => null, - 'geometry' => null - ]; - - if (!$address || !$zipCode || !$town) { - return $result; - } - - $query = sprintf('%s %s %s', $address, $zipCode, $town); - try { - $response = $client->request('GET', 'https://api-adresse.data.gouv.fr/search/', [ - 'query' => [ - 'q' => $query, - 'limit' => 1 - ] - ]); - - $content = $response->toArray(); - - if (!empty($content['features'])) { - $coords = $content['features'][0]['geometry']['coordinates']; - $lon = $coords[0]; - $lat = $coords[1]; - - // Point de départ (LudikEvent) - $startLat = 49.849; - $startLon = 3.286; - - // Calcul itinéraire via API Geoplateforme - $itineraireResponse = $client->request('GET', 'https://data.geopf.fr/navigation/itineraire', [ - 'query' => [ - 'resource' => 'bdtopo-osrm', - 'start' => $startLon . ',' . $startLat, - 'end' => $lon . ',' . $lat, - 'profile' => 'car', - 'optimization' => 'fastest', - 'distanceUnit' => 'kilometer', - 'geometryFormat' => 'geojson' - ] - ]); - - $itineraire = $itineraireResponse->toArray(); - $distance = $itineraire['distance']; - $result['geometry'] = $itineraire['geometry'] ?? null; - - $rate = 0.50; - $trips = 4; - - if ($distance <= 10) { - $result['estimation'] = 0.0; - $chargedDistance = 0.0; - } else { - $chargedDistance = $distance - 10; - $result['estimation'] = ($chargedDistance * $trips) * $rate; - } - - $result['details'] = [ - 'distance' => $distance, - 'chargedDistance' => $chargedDistance, - 'trips' => $trips, - 'rate' => $rate, - 'isFree' => ($distance <= 10) - ]; - } - } catch (\Exception $e) { - // Return default nulls on error - } - - return $result; - } private function buildCartData(array $products, array $selectedOptionsMap, int $duration, OptionsRepository $optionsRepository, UploaderHelper $uploaderHelper, ?Promotion $promotion = null, ?Formules $formule = null): array { diff --git a/src/Service/Pdf/ContratPdfService.php b/src/Service/Pdf/ContratPdfService.php index 11abb08..edc4567 100644 --- a/src/Service/Pdf/ContratPdfService.php +++ b/src/Service/Pdf/ContratPdfService.php @@ -239,7 +239,7 @@ class ContratPdfService extends Fpdf "ARTICLE 6 – CAUTION DE GARANTIE" => "Une caution de garantie peut être exigée selon le type et la valeur du matériel loué :\n• Structures professionnelles Lilian SEGARD - Ludikevent | Selon devis | Restitution immédiate après état des lieux de fin de location et contrôle de conformité\n• Matériel mis en relation (propriétaires privés) | Selon convention propriétaire | Restitution selon accord entre parties\nLa caution peut être conservée totalement ou partiellement en cas de : dégradation du matériel, salissure importante nécessitant un nettoyage approfondi, perte d'éléments ou d'accessoires, non-respect des conditions d'utilisation ayant entraîné des dommages.", - "ARTICLE 7 – LIVRAISON, INSTALLATION ET RÉCUPÉRATION" => "7.1 – Structures professionnelles Lilian SEGARD - Ludikevent :\nInstallation : L'installation est réalisée exclusivement par le personnel qualifié de Lilian SEGARD - Ludikevent. Le Client doit fournir un terrain plat, propre, dégagé, avec une alimentation électrique 220V à moins de 50 mètres. L'accès doit être praticable pour les véhicules.\nRécupération : La récupération du matériel est effectuée par Lilian SEGARD - Ludikevent aux horaires convenus.\n7.2 – Matériel en mise en relation :\nLilian SEGARD - Ludikevent peut assurer l'installation et la récupération pour le compte du propriétaire privé. Le Client locataire reste tenu d'assurer une surveillance permanente et constante. Des frais de déplacement supplémentaires peuvent s'appliquer au-delà d'un rayon de 30 km depuis Danizy.", + "ARTICLE 7 – LIVRAISON, INSTALLATION ET RÉCUPÉRATION" => "7.1 – Structures professionnelles Lilian SEGARD - Ludikevent :\nInstallation : L'installation est réalisée exclusivement par le personnel qualifié de Lilian SEGARD - Ludikevent. Le Client doit fournir un terrain plat, propre, dégagé, avec une alimentation électrique 220V à moins de 50 mètres. L'accès doit être praticable pour les véhicules.\nRécupération : La récupération du matériel est effectuée par Lilian SEGARD - Ludikevent aux horaires convenus.", "ARTICLE 8 – ÉTATS DES LIEUX ET TRANSFERT DE RESPONSABILITÉ" => "8.1 – État des lieux d'installation : Un état des lieux contradictoire est OBLIGATOIREMENT réalisé. La signature par le Client vaut reconnaissance de conformité et TRANSFERT COMPLET DE LA RESPONSABILITÉ DU MATÉRIEL AU CLIENT. Le Client assume l'ENTIÈRE et EXCLUSIVE responsabilité du matériel, de son utilisation, de sa surveillance et des dommages qui pourraient en résulter.\n8.2 – État des lieux de fin de location : Un état des lieux contradictoire est réalisé lors de la récupération. Sa signature vaut RETOUR DE LA RESPONSABILITÉ À Lilian SEGARD - Ludikevent.\n8.3 – Absence de signature : En cas d'absence ou de refus de signature, l'état des lieux établi par Lilian SEGARD - Ludikevent fera foi. Le matériel sera réputé avoir été livré en parfait état et la responsabilité du Client reste pleine et entière durant toute la période de location.", diff --git a/src/Service/Pdf/DevisPdfService.php b/src/Service/Pdf/DevisPdfService.php index 30a8112..c3e29e7 100644 --- a/src/Service/Pdf/DevisPdfService.php +++ b/src/Service/Pdf/DevisPdfService.php @@ -383,7 +383,7 @@ class DevisPdfService extends Fpdf "ARTICLE 6 – CAUTION DE GARANTIE" => "Une caution de garantie peut être exigée selon le type et la valeur du matériel loué :\n• Structures professionnelles Lilian SEGARD - Ludikevent | Selon devis | Restitution immédiate après état des lieux de fin de location et contrôle de conformité\n• Matériel mis en relation (propriétaires privés) | Selon convention propriétaire | Restitution selon accord entre parties\nLa caution peut être conservée totalement ou partiellement en cas de : dégradation du matériel, salissure importante nécessitant un nettoyage approfondi, perte d'éléments ou d'accessoires, non-respect des conditions d'utilisation ayant entraîné des dommages.", - "ARTICLE 7 – LIVRAISON, INSTALLATION ET RÉCUPÉRATION" => "7.1 – Structures professionnelles Lilian SEGARD - Ludikevent :\nInstallation : L'installation est réalisée exclusivement par le personnel qualifié de Lilian SEGARD - Ludikevent. Le Client doit fournir un terrain plat, propre, dégagé, avec une alimentation électrique 220V à moins de 50 mètres. L'accès doit être praticable pour les véhicules.\nRécupération : La récupération du matériel est effectuée par Lilian SEGARD - Ludikevent aux horaires convenus.\n7.2 – Matériel en mise en relation :\nLilian SEGARD - Ludikevent peut assurer l'installation et la récupération pour le compte du propriétaire privé. Le Client locataire reste tenu d'assurer une surveillance permanente et constante. Des frais de déplacement supplémentaires peuvent s'appliquer au-delà d'un rayon de 30 km depuis Danizy.", + "ARTICLE 7 – LIVRAISON, INSTALLATION ET RÉCUPÉRATION" => "7.1 – Structures professionnelles Lilian SEGARD - Ludikevent :\nInstallation : L'installation est réalisée exclusivement par le personnel qualifié de Lilian SEGARD - Ludikevent. Le Client doit fournir un terrain plat, propre, dégagé, avec une alimentation électrique 220V à moins de 50 mètres. L'accès doit être praticable pour les véhicules.\nRécupération : La récupération du matériel est effectuée par Lilian SEGARD - Ludikevent aux horaires convenus.", "ARTICLE 8 – ÉTATS DES LIEUX ET TRANSFERT DE RESPONSABILITÉ" => "8.1 – État des lieux d'installation : Un état des lieux contradictoire est OBLIGATOIREMENT réalisé. La signature par le Client vaut reconnaissance de conformité et TRANSFERT COMPLET DE LA RESPONSABILITÉ DU MATÉRIEL AU CLIENT. Le Client assume l'ENTIÈRE et EXCLUSIVE responsabilité du matériel, de son utilisation, de sa surveillance et des dommages qui pourraient en résulter.\n8.2 – État des lieux de fin de location : Un état des lieux contradictoire est réalisé lors de la récupération. Sa signature vaut RETOUR DE LA RESPONSABILITÉ À Lilian SEGARD - Ludikevent.\n8.3 – Absence de signature : En cas d'absence ou de refus de signature, l'état des lieux établi par Lilian SEGARD - Ludikevent fera foi. Le matériel sera réputé avoir été livré en parfait état et la responsabilité du Client reste pleine et entière durant toute la période de location.", diff --git a/templates/dashboard/flow/view.twig b/templates/dashboard/flow/view.twig index 4c7b9ca..a0c1a5d 100644 --- a/templates/dashboard/flow/view.twig +++ b/templates/dashboard/flow/view.twig @@ -4,16 +4,9 @@ {% block title_header %}Réservation #{{ session.id }}{% endblock %} {% block body %} - - -
- {% set isActionable = session.deliveryPrice is not null and session.typePaiement %} + {% set isActionable = session.typePaiement %}
@@ -43,26 +36,16 @@ - {# BILLING & DELIVERY CONFIG #} + {# BILLING CONFIG #}

- Configuration Facturation & Livraison + Configuration Facturation

-
-
- - -
-
- - -
+
-
-
- - +
+ + +
- {% if session.deliveryDistance is not null %} -
-

Détails Livraison

- -
- {# Map #} - {% if session.deliveryGeometry %} -
- - -
- {% endif %} - - {# Details #} -
-
- Distance réelle (Aller) - {{ session.deliveryDistance|number_format(1, ',', ' ') }} km -
-
- Franchise - - 10.0 km -
-
- Distance facturée - {{ max(0, session.deliveryDistance - 10)|number_format(1, ',', ' ') }} km -
-
- Trajets - 4 (2 A/R) -
-
- - ({{ session.deliveryDistance|number_format(1) }} - 10) x 4 x 0.50€ = {{ session.deliveryPrice|number_format(2) }}€ - -
-
-
-
- {% endif %} - -
diff --git a/templates/revervation/base.twig b/templates/revervation/base.twig index a9182c0..f0f8d9c 100644 --- a/templates/revervation/base.twig +++ b/templates/revervation/base.twig @@ -133,7 +133,6 @@ {{ macros.nav_link('reservation_catalogue', 'nav.catalogue') }} {{ macros.nav_link('reservation_formules', 'nav.packages') }} {{ macros.nav_link('/images/Catalogue.pdf', 'nav.pdf', true) }} - {{ macros.nav_link('reservation_estimate_delivery', 'Estimer la livraison') }} {{ macros.nav_link('reservation_contact', 'nav.contact') }} @@ -189,7 +188,6 @@ {{ macros.mobile_nav_link('reservation_catalogue', 'Nos structures') }} {{ macros.mobile_nav_link('reservation_formules', 'Nos Formules') }} {{ macros.mobile_nav_link('/images/Catalogue.pdf', 'Catalogue', true) }} - {{ macros.mobile_nav_link('reservation_estimate_delivery', 'Estimer la livraison') }} {{ macros.mobile_nav_link('reservation_search', 'Rechercher') }} Panier diff --git a/templates/revervation/cgv.twig b/templates/revervation/cgv.twig index f70d67a..1a54605 100644 --- a/templates/revervation/cgv.twig +++ b/templates/revervation/cgv.twig @@ -510,14 +510,6 @@
- {# Frais de déplacement #} -
- 🌍 -

- Livraison incluse dans un rayon de 30 km depuis Danizy. - Des frais de déplacement s'appliquent au-delà. -

-
diff --git a/templates/revervation/estimate_delivery.twig b/templates/revervation/estimate_delivery.twig deleted file mode 100644 index 4dd3322..0000000 --- a/templates/revervation/estimate_delivery.twig +++ /dev/null @@ -1,134 +0,0 @@ -{% extends 'revervation/base.twig' %} - -{% block title %}Estimer les frais de livraison | Ludik Event{% endblock %} - -{% block stylesheets %} - {{ parent() }} - -{% endblock %} - -{% block body %} -
-
-

- Estimer la livraison -

- -
-

- Renseignez l'adresse de votre événement pour obtenir une estimation des frais de livraison. -

- - {{ form_start(form, {'attr': {'class': 'space-y-6', 'data-turbo': 'false'}}) }} - -
- {{ form_label(form.address, 'Adresse complète', {'label_attr': {'class': 'text-[10px] font-black text-slate-400 uppercase tracking-widest ml-1 mb-2 block'}}) }} - {{ form_widget(form.address, {'attr': {'class': 'w-full bg-white border border-slate-200 rounded-2xl px-5 py-4 text-slate-900 outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 transition-all', 'placeholder': 'Ex: 10 rue de la Paix'}}) }} -
- -
-
- {{ form_label(form.zipCode, 'Code Postal', {'label_attr': {'class': 'text-[10px] font-black text-slate-400 uppercase tracking-widest ml-1 mb-2 block'}}) }} - {{ form_widget(form.zipCode, {'attr': {'class': 'w-full bg-white border border-slate-200 rounded-2xl px-5 py-4 text-slate-900 outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 transition-all', 'placeholder': '02000'}}) }} -
-
- {{ form_label(form.city, 'Ville', {'label_attr': {'class': 'text-[10px] font-black text-slate-400 uppercase tracking-widest ml-1 mb-2 block'}}) }} - {{ form_widget(form.city, {'attr': {'class': 'w-full bg-white border border-slate-200 rounded-2xl px-5 py-4 text-slate-900 outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 transition-all', 'placeholder': 'Laon'}}) }} -
-
- -
- -
- - {{ form_end(form) }} - - {% if estimation is defined and estimation is not null %} -
-
- Résultat de l'estimation - {% if details.isFree %} -
- Offert ! - Zone gratuite -
-

Votre événement se trouve à moins de 10km de nos locaux.

- {% else %} -

- {{ estimation|format_currency('EUR') }} -

- {% endif %} -
- - {% if details is defined %} -
-

Détails du calcul

- -
- Distance réelle (Aller) - {{ details.distance|number_format(1, ',', ' ') }} km -
- -
- Franchise kilométrique - - 10.0 km (Offerts) -
- -
- -
- Distance facturée - {{ details.chargedDistance|number_format(1, ',', ' ') }} km -
- -
- Nombre de trajets - {{ details.trips }} (2 A/R) -
- -
- Tarif kilométrique - {{ details.rate }} € / km -
- - {% if not details.isFree %} -
- - ({{ details.distance|number_format(1) }} - 10) x {{ details.trips }} x {{ details.rate }}€ = {{ estimation|number_format(2) }}€ - -
- {% endif %} -
- {% endif %} - - {% if geometry is defined and geometry is not null %} - - - {% endif %} - -
-

- Cette estimation est donnée à titre indicatif et sera confirmée lors de la validation de votre devis. -

-
-
- {% endif %} -
-
-
-{% endblock %} - -{% block javascripts %} - {{ parent() }} - {% if geometry is defined and geometry is not null %} - - {% endif %} -{% endblock %} diff --git a/templates/revervation/flow_confirmed.twig b/templates/revervation/flow_confirmed.twig index 2b8eed6..9860c52 100644 --- a/templates/revervation/flow_confirmed.twig +++ b/templates/revervation/flow_confirmed.twig @@ -273,100 +273,6 @@ - {# Delivery Estimation #} - {% if delivery is defined and delivery.estimation is not null %} -
-
-
- - - -
-

Estimation des frais de livraison

-
- -
- {# Details (60%) #} -
- {% if delivery.details.isFree %} -
-
- Offert ! - Zone gratuite -
-

Votre événement se trouve à moins de 10km de nos locaux.

-
- {% else %} -
- Coût estimé -

- {{ delivery.estimation|format_currency('EUR') }} -

-
- {% endif %} - -
-

Détails du calcul

- -
- Distance réelle (Aller) - {{ delivery.details.distance|number_format(1, ',', ' ') }} km -
- -
- Franchise kilométrique - - 10.0 km (Offerts) -
- -
- -
- Distance facturée - {{ delivery.details.chargedDistance|number_format(1, ',', ' ') }} km -
- -
- Nombre de trajets - {{ delivery.details.trips }} (2 A/R) -
- -
- Tarif kilométrique - {{ delivery.details.rate }} € / km -
-
- - {% if not delivery.details.isFree %} -
-

Formule appliquée

- - ({{ delivery.details.distance|number_format(1) }} - 10) x {{ delivery.details.trips }} x {{ delivery.details.rate }}€ = {{ delivery.estimation|number_format(2) }}€ - -
- {% endif %} - -
-

- Cette estimation est indicative. Le montant définitif figurera sur votre devis. -

-
-
- - {# Map (40%) #} -
- {% if delivery.geometry %} - - - {% else %} -
- Carte non disponible -
- {% endif %} -
-
-
- {% endif %}