templates/facture_service/show.html.twig line 1

Open in your IDE?
  1. {% extends 'basee.html.twig' %}
  2. {% block title %}Facture de Service{% endblock %}
  3. {% block subtitle %}Facture de Service{% endblock %}
  4. {% block subtitle2 %}Détails de la Facture{% endblock %}
  5. {% block body %}
  6.     <div class="row">
  7.         <div class="col-md-12">
  8.             <div class="card">
  9.                 <div class="card-header pb-0">
  10.                     <div class="d-flex align-items-center">
  11.                         <p class="mb-0">Détails de la Facture</p>
  12.                     </div>
  13.                 </div>
  14.                 <div class="card-body">
  15.                     <div class="row">
  16.                         <div class="col-md-6">
  17.                             <div class="form-group">
  18.                                 <label class="form-control-label" style="font-weight:bold">Id</label>
  19.                                 <p>{{ facture_service.id }}</p>
  20.                             </div>
  21.                         </div>
  22.                         <div class="col-md-6">
  23.                             <div class="form-group">
  24.                                 <label class="form-control-label" style="font-weight:bold">Numéro</label>
  25.                                 <p>{{ facture_service.numero }}</p>
  26.                             </div>
  27.                         </div>
  28.                         <div class="col-md-6">
  29.                             <div class="form-group">
  30.                                 <label class="form-control-label" style="font-weight:bold">Date de création</label>
  31.                                 <p>{{ facture_service.dateCreation ? facture_service.dateCreation|date('d/m/Y H:i') : 'N/A' }}</p>
  32.                             </div>
  33.                         </div>
  34.                         <div class="col-md-6">
  35.                             <div class="form-group">
  36.                                 <label class="form-control-label" style="font-weight:bold">Status</label>
  37.                                 <select id="statut-facture" class="form-select">
  38.                                     <option value="En attente" {{ facture_service.status == 'En attente' ? 'selected' }}>En attente</option>
  39.                                     <option value="Partiellement payé" {{ facture_service.status == 'Partiellement payé' ? 'selected' }}>Partiellement payé</option>
  40.                                     <option value="Payé" {{ facture_service.status == 'Payé' ? 'selected' }}>Payé</option>
  41.                                     <option value="Annulé" {{ facture_service.status == 'Annulé' ? 'selected' }}>Annulé</option>
  42.                                 </select>
  43.                             </div>
  44.                         </div>
  45.                         <div class="col-md-6">
  46.                             <div class="form-group">
  47.                                 <label class="form-control-label" style="font-weight:bold">Client</label>
  48.                                 <p>{{ facture_service.client ? facture_service.client.nom : 'Non spécifié' }}</p>
  49.                             </div>
  50.                         </div>
  51.                         <div class="col-md-6">
  52.                             <div class="form-group">
  53.                                 <label class="form-control-label" style="font-weight:bold">Type de Paiement</label>
  54.                                 <select id="type-paiement" class="form-select">
  55.                                     <option value="Espèces" {{ facture_service.typePaiement == 'Espèces' ? 'selected' }}>Espèces</option>
  56.                                     <option value="Yas" {{ facture_service.typePaiement == 'Yas' ? 'selected' }}>Yas</option>
  57.                                     <option value="Flooz" {{ facture_service.typePaiement == 'Flooz' ? 'selected' }}>Flooz</option>
  58.                                     <option value="TPE" {{ facture_service.typePaiement == 'TPE' ? 'selected' }}>TPE</option>
  59.                                     <option value="WAVE" {{ facture_service.typePaiement == 'WAVE' ? 'selected' }}>WAVE</option>
  60.                                     <option value="ORANGE MONEY" {{ facture_service.typePaiement == 'ORANGE MONEY' ? 'selected' }}>ORANGE MONEY</option>
  61.                                     <option value="VIREMENT BANCAIRE" {{ facture_service.typePaiement == 'VIREMENT BANCAIRE' ? 'selected' }}>VIREMENT BANCAIRE</option>
  62.                                 </select>
  63.                             </div>
  64.                         </div>
  65.                     </div>
  66.                     <hr class="horizontal dark">
  67.                     <h3>Services facturés</h3>
  68.                     {% if facture_service.serviceFactureLignes|length > 0 %}
  69.                         <form id="update-services-form">
  70.                             <table class="table table-striped">
  71.                                 <thead>
  72.                                     <tr>
  73.                                         <th>Service</th>
  74.                                         <th class="text-end">Prix</th>
  75.                                     </tr>
  76.                                 </thead>
  77.                                 <tbody>
  78.                                     {% for ligne in facture_service.serviceFactureLignes %}
  79.                                         <tr>
  80.                                             <td>{{ ligne.service ? ligne.service.nom : 'Service inconnu' }}</td>
  81.                                             <td class="text-end">
  82.                                                 <input type="number" 
  83.                                                        class="form-control service-prix text-end" 
  84.                                                        value="{{ ligne.prix }}" 
  85.                                                        data-ligne-id="{{ ligne.id }}"
  86.                                                        data-original-prix="{{ ligne.prix }}"
  87.                                                        step="0.01" min="0">
  88.                                             </td>
  89.                                         </tr>
  90.                                     {% endfor %}
  91.                                     <tr class="table-active">
  92.                                         <th>Montant total</th>
  93.                                         <th class="text-end" id="montant-total">{{ facture_service.montantTotal|number_format(2, ',', ' ') }} CFA</th>
  94.                                     </tr>
  95.                                 </tbody>
  96.                             </table>
  97.                             <div class="text-end mt-3">
  98.                                 <button type="button" id="reset-prix-btn" class="btn btn-outline-secondary btn-sm">Réinitialiser les prix</button>
  99.                                 <button type="submit" class="btn btn-primary btn-sm">Enregistrer les modifications</button>
  100.                             </div>
  101.                         </form>
  102.                     {% else %}
  103.                         <div class="alert alert-info">Aucun service associé à cette facture.</div>
  104.                     {% endif %}
  105.                 </div>
  106.                 <div class="card-footer d-flex align-items-center">
  107.                     <a href="{{ path('app_facture_service_index') }}" class="btn btn-outline-secondary btn-sm ms-auto me-4">Retour à la liste</a>
  108.                     <a href="{{ path('app_facture_service_edit', {'id': facture_service.id}) }}" class="btn btn-outline-primary btn-sm me-4">Modifier</a>
  109.                     <button onclick="imprimerFacture({{ facture_service.id }})" class="btn btn-outline-secondary btn-sm">
  110.                         <i class="bi bi-printer"></i> Imprimer la facture
  111.                     </button>
  112.                 </div>
  113.             </div>
  114.         </div>
  115.     </div>
  116.     <script>
  117.         document.addEventListener('DOMContentLoaded', function() {
  118.             const statutFactureSelect = document.getElementById('statut-facture');
  119.             const typePaiementSelect = document.getElementById('type-paiement');
  120.             const servicePrixInputs = document.querySelectorAll('.service-prix');
  121.             const montantTotalElement = document.getElementById('montant-total');
  122.             const updateServicesForm = document.getElementById('update-services-form');
  123.             const resetPrixBtn = document.getElementById('reset-prix-btn');
  124.             
  125.             // Fonction pour mettre à jour le type de paiement
  126.             typePaiementSelect.addEventListener('change', function() {
  127.                 const factureId = {{ facture_service.id }};
  128.                 const nouveauType = this.value;
  129.                 
  130.                 fetch("{{ path('app_facture_service_update_type_paiement') }}", {
  131.                     method: "POST",
  132.                     headers: {
  133.                         "Content-Type": "application/json",
  134.                         "X-Requested-With": "XMLHttpRequest"
  135.                     },
  136.                     body: JSON.stringify({
  137.                         id: factureId,
  138.                         typePaiement: nouveauType
  139.                     })
  140.                 })
  141.                 .then(response => response.json())
  142.                 .then(data => {
  143.                     if (data.success) {
  144.                         // Afficher une notification de succès
  145.                         const notification = document.createElement('div');
  146.                         notification.className = 'alert alert-success alert-dismissible fade show';
  147.                         notification.innerHTML = `
  148.                             Type de paiement mis à jour avec succès !
  149.                             <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
  150.                         `;
  151.                         document.querySelector('.card-body').prepend(notification);
  152.                         
  153.                         // Suppression automatique après 3 secondes
  154.                         setTimeout(() => {
  155.                             notification.remove();
  156.                         }, 3000);
  157.                     } else {
  158.                         alert("Erreur lors de la mise à jour du type de paiement : " + data.message);
  159.                     }
  160.                 })
  161.                 .catch(error => {
  162.                     console.error("Erreur:", error);
  163.                     alert("Une erreur s'est produite lors de la mise à jour du type de paiement.");
  164.                 });
  165.             });
  166.             
  167.             // Fonction pour mettre à jour le statut de la facture
  168.             statutFactureSelect.addEventListener('change', function() {
  169.                 const factureId = {{ facture_service.id }};
  170.                 const nouveauStatut = this.value;
  171.                 
  172.                 fetch("{{ path('app_facture_service_update_status') }}", {
  173.                     method: "POST",
  174.                     headers: {
  175.                         "Content-Type": "application/json",
  176.                         "X-Requested-With": "XMLHttpRequest"
  177.                     },
  178.                     body: JSON.stringify({
  179.                         id: factureId,
  180.                         status: nouveauStatut
  181.                     })
  182.                 })
  183.                 .then(response => response.json())
  184.                 .then(data => {
  185.                     if (data.success) {
  186.                         alert("Le statut de la facture a été mis à jour avec succès.");
  187.                     } else {
  188.                         alert("Erreur lors de la mise à jour du statut : " + data.message);
  189.                     }
  190.                 })
  191.                 .catch(error => {
  192.                     console.error("Erreur:", error);
  193.                     alert("Une erreur s'est produite lors de la mise à jour du statut.");
  194.                 });
  195.             });
  196.             
  197.             // Fonction pour calculer le montant total
  198.             function calculerMontantTotal() {
  199.                 let total = 0;
  200.                 servicePrixInputs.forEach(input => {
  201.                     total += parseFloat(input.value) || 0;
  202.                 });
  203.                 return total;
  204.             }
  205.             
  206.             // Mise à jour du montant total lors de la modification des prix
  207.             servicePrixInputs.forEach(input => {
  208.                 input.addEventListener('input', function() {
  209.                     const total = calculerMontantTotal();
  210.                     montantTotalElement.textContent = total.toLocaleString('fr-FR', {
  211.                         minimumFractionDigits: 2,
  212.                         maximumFractionDigits: 2
  213.                     }) + ' CFA';
  214.                 });
  215.             });
  216.             
  217.             // Réinitialiser les prix
  218.             resetPrixBtn.addEventListener('click', function() {
  219.                 servicePrixInputs.forEach(input => {
  220.                     input.value = input.dataset.originalPrix;
  221.                 });
  222.                 
  223.                 // Mettre à jour le montant total
  224.                 const total = calculerMontantTotal();
  225.                 montantTotalElement.textContent = total.toLocaleString('fr-FR', {
  226.                     minimumFractionDigits: 2,
  227.                     maximumFractionDigits: 2
  228.                 }) + ' CFA';
  229.             });
  230.             
  231.             // Enregistrer les modifications
  232.             updateServicesForm.addEventListener('submit', function(e) {
  233.                 e.preventDefault();
  234.                 
  235.                 const factureId = {{ facture_service.id }};
  236.                 const lignes = [];
  237.                 
  238.                 servicePrixInputs.forEach(input => {
  239.                     lignes.push({
  240.                         id: input.dataset.ligneId,
  241.                         prix: parseFloat(input.value)
  242.                     });
  243.                 });
  244.                 
  245.                 const montantTotal = calculerMontantTotal();
  246.                 
  247.                 fetch("{{ path('app_facture_service_update_prix') }}", {
  248.                     method: "POST",
  249.                     headers: {
  250.                         "Content-Type": "application/json",
  251.                         "X-Requested-With": "XMLHttpRequest"
  252.                     },
  253.                     body: JSON.stringify({
  254.                         factureId: factureId,
  255.                         lignes: lignes,
  256.                         montantTotal: montantTotal
  257.                     })
  258.                 })
  259.                 .then(response => response.json())
  260.                 .then(data => {
  261.                     if (data.success) {
  262.                         alert("Les prix ont été mis à jour avec succès.");
  263.                         
  264.                         // Mettre à jour les prix originaux
  265.                         servicePrixInputs.forEach(input => {
  266.                             input.dataset.originalPrix = input.value;
  267.                         });
  268.                     } else {
  269.                         alert("Erreur lors de la mise à jour des prix : " + data.message);
  270.                     }
  271.                 })
  272.                 .catch(error => {
  273.                     console.error("Erreur:", error);
  274.                     alert("Une erreur s'est produite lors de la mise à jour des prix.");
  275.                 });
  276.             });
  277.         });
  278.         
  279.         // Fonction pour imprimer la facture
  280.         function imprimerFacture(id) {
  281.             const url = "{{ path('app_facture_service_print', {'id': 'REPLACE_ID'}) }}".replace('REPLACE_ID', id);
  282.             window.open(url, '_blank');
  283.         }
  284.     </script>
  285. {% endblock %}