Formulaire de Devis Peinture - Professionnel
';
suggestionsDiv.style.display = 'block';
// Essayer d'abord l'API de recherche d'entreprises officielle
searchEntreprisesAPI1(query)
.catch(error => {
console.warn('API principale indisponible, essai API alternative:', error);
return searchEntreprisesAPI2(query);
})
.catch(error => {
console.warn('API alternative indisponible, mode fallback:', error);
return searchEntreprisesFallback(query);
})
.then(data => {
if (data && data.length > 0) {
displaySuggestions(data);
} else {
suggestionsDiv.innerHTML = `
🔍 Aucune entreprise trouvée pour "${query}"
Vous pouvez saisir manuellement les informations
`;
}
})
.catch(error => {
console.error('Toutes les APIs sont indisponibles:', error);
suggestionsDiv.innerHTML = `
`;
});
}
// API 1: Recherche d'entreprises officielle
function searchEntreprisesAPI1(query) {
const url = `https://recherche-entreprises.api.gouv.fr/search?q=${encodeURIComponent(query)}&per_page=8&page=1`;
return fetch(url, {
method: 'GET',
headers: {
'Accept': 'application/json',
}
})
.then(response => {
if (!response.ok) {
throw new Error(`API 1 Error: ${response.status}`);
}
return response.json();
})
.then(data => {
// Convertir le format de l'API officielle
return (data.results || []).map(entreprise => ({
nom_raison_sociale: entreprise.nom_complet || entreprise.nom_raison_sociale,
siret: entreprise.siege?.siret || '',
siren: entreprise.siren || '',
numero_voie: entreprise.siege?.numero_voie || '',
type_voie: entreprise.siege?.type_voie || '',
libelle_voie: entreprise.siege?.libelle_voie || '',
code_postal: entreprise.siege?.code_postal || '',
libelle_commune: entreprise.siege?.libelle_commune || '',
code_commune: entreprise.siege?.code_commune || ''
}));
});
}
// API 2: Alternative avec API Sirene publique
function searchEntreprisesAPI2(query) {
// Utiliser l'ancienne API en tant que fallback
const url = `https://entreprise.data.gouv.fr/api/sirene/v1/full_text/${encodeURIComponent(query)}?per_page=8`;
return fetch(url, {
method: 'GET',
headers: {
'Accept': 'application/json',
}
})
.then(response => {
if (!response.ok) {
throw new Error(`API 2 Error: ${response.status}`);
}
return response.json();
})
.then(data => {
return data.etablissement || [];
});
}
// Fallback: Base de données statique pour les entreprises les plus courantes
function searchEntreprisesFallback(query) {
return new Promise((resolve) => {
// Base de données minimale pour les tests
const entreprisesComunes = [
{
nom_raison_sociale: "SOS PEINTURE",
siret: "12345678901234",
siren: "123456789",
numero_voie: "123",
type_voie: "RUE",
libelle_voie: "DE LA PAIX",
code_postal: "75001",
libelle_commune: "PARIS",
code_commune: "75101"
},
{
nom_raison_sociale: "PEINTURE EXPRESS",
siret: "98765432109876",
siren: "987654321",
numero_voie: "456",
type_voie: "AVENUE",
libelle_voie: "DES ARTISANS",
code_postal: "69000",
libelle_commune: "LYON",
code_commune: "69123"
}
];
const queryLower = query.toLowerCase();
const results = entreprisesComunes.filter(entreprise =>
entreprise.nom_raison_sociale.toLowerCase().includes(queryLower)
);
setTimeout(() => resolve(results), 300); // Simuler un délai réseau
});
}
// Affichage des suggestions
function displaySuggestions(entreprises) {
const suggestionsDiv = document.getElementById('entrepriseSuggestions');
currentFocus = -1;
if (entreprises.length === 0) {
suggestionsDiv.innerHTML = '
🔍 Aucune entreprise trouvée
';
return;
}
let html = '';
entreprises.forEach((entreprise, index) => {
const nom = entreprise.nom_raison_sociale || entreprise.l1_normalisee || 'Nom non disponible';
const adresse = `${entreprise.numero_voie || ''} ${entreprise.type_voie || ''} ${entreprise.libelle_voie || ''}`.trim();
const ville = `${entreprise.code_postal || ''} ${entreprise.libelle_commune || ''}`.trim();
const siret = entreprise.siret || '';
html += `
${nom}
${adresse}${adresse && ville ? ', ' : ''}${ville}
${siret ? `${siret}` : ''}
`;
});
suggestionsDiv.innerHTML = html;
// Ajouter les événements de clic
document.querySelectorAll('.autocomplete-suggestion').forEach((item, index) => {
item.addEventListener('click', () => {
selectEntreprise(entreprises[index]);
});
item.addEventListener('mouseenter', () => {
currentFocus = index;
addActive(document.querySelectorAll('.autocomplete-suggestion'));
});
});
}
// Sélection d'une entreprise
function selectEntreprise(entreprise) {
selectedEntreprise = {
nom: entreprise.nom_raison_sociale || entreprise.l1_normalisee || '',
siret: entreprise.siret || '',
siren: entreprise.siren || '',
adresse: `${entreprise.numero_voie || ''} ${entreprise.type_voie || ''} ${entreprise.libelle_voie || ''}`.trim(),
codePostal: entreprise.code_postal || '',
ville: entreprise.libelle_commune || '',
codeCommunune: entreprise.code_commune || ''
};
const nomClientInput = document.getElementById('Nom_Client');
// Remplir les champs
nomClientInput.value = selectedEntreprise.nom;
nomClientInput.classList.add('entreprise-selected');
document.getElementById('Siret_Client').value = selectedEntreprise.siret;
// Construire l'adresse complète pour l'adresse du client (siège social)
const adresseComplete = `${selectedEntreprise.adresse}, ${selectedEntreprise.codePostal} ${selectedEntreprise.ville}`.replace(/^,\s*/, '');
document.getElementById('Adresse_Client').value = adresseComplete;
// Si "même adresse" est cochée, copier aussi vers l'adresse chantier
const memeAdresseCheckbox = document.getElementById('memeAdresse');
if (memeAdresseCheckbox.checked) {
document.getElementById('Adresse_Chantier').value = adresseComplete;
}
// Afficher les infos de l'entreprise sélectionnée
document.getElementById('entrepriseDetails').innerHTML = `
${selectedEntreprise.nom}
SIRET: ${selectedEntreprise.siret}
Adresse siège: ${adresseComplete}
`;
document.getElementById('entrepriseInfo').style.display = 'block';
// Afficher le bouton effacer
document.getElementById('clearEntreprise').style.display = 'block';
hideSuggestions();
}
// Effacer la sélection d'entreprise
function clearEntrepriseSelection() {
selectedEntreprise = null;
const nomClientInput = document.getElementById('Nom_Client');
const memeAdresseCheckbox = document.getElementById('memeAdresse');
const checkboxLabel = document.querySelector('.checkbox-same-address');
nomClientInput.value = '';
nomClientInput.classList.remove('entreprise-selected');
document.getElementById('Siret_Client').value = '';
document.getElementById('Adresse_Client').value = '';
document.getElementById('Adresse_Chantier').value = '';
document.getElementById('entrepriseInfo').style.display = 'none';
document.getElementById('clearEntreprise').style.display = 'none';
document.getElementById('manualSearch').style.display = 'none';
// Réinitialiser la checkbox "même adresse"
memeAdresseCheckbox.checked = false;
checkboxLabel.classList.remove('active');
hideSuggestions();
}
// Masquer les suggestions
function hideSuggestions() {
document.getElementById('entrepriseSuggestions').style.display = 'none';
currentFocus = -1;
}
// Ajouter la classe active à la suggestion sélectionnée
function addActive(suggestions) {
suggestions.forEach(item => item.classList.remove('active'));
if (currentFocus >= 0 && suggestions[currentFocus]) {
suggestions[currentFocus].classList.add('active');
}
}
// Calcul automatique de la surface et du prix
function calculerSurface() {
const longueur = parseFloat(document.getElementById('longueur').value) || 0;
const largeur = parseFloat(document.getElementById('largeur').value) || 0;
const hauteur = parseFloat(document.getElementById('hauteur').value) || 0;
const portesNb = parseInt(document.getElementById('portes_nb').value) || 0;
const fenetresNb = parseInt(document.getElementById('fenetres_nb').value) || 0;
const surfaceManuelle = parseFloat(document.getElementById('surface_manuelle').value) || 0;
let surface = 0;
if (surfaceManuelle > 0) {
surface = surfaceManuelle;
} else {
// Calcul automatique
const surfaceSol = longueur * largeur;
const surfaceMurs = 2 * (longueur + largeur) * hauteur;
// Déduction des ouvertures (estimation)
const surfacePortes = portesNb * 2; // 2m² par porte
const surfaceFenetres = fenetresNb * 1.5; // 1.5m² par fenêtre
// Surface totale selon les éléments sélectionnés
const surfacesSelectionnees = document.querySelectorAll('input[name="surfaces[]"]:checked');
surfacesSelectionnees.forEach(surface_elem => {
switch(surface_elem.value) {
case 'murs':
surface += surfaceMurs - surfacePortes - surfaceFenetres;
break;
case 'plafond':
surface += surfaceSol;
break;
case 'portes':
surface += surfacePortes;
break;
case 'fenetres':
surface += surfaceFenetres;
break;
case 'radiateurs':
surface += portesNb * 0.5; // Estimation
break;
}
});
}
document.getElementById('surfaceTotal').textContent = surface.toFixed(2) + ' m²';
calculerPrix(surface);
}
function calculerPrix(surface) {
// Paliers de tarification
let prixUnitaire = 0;
let surfaceFacturee = surface;
// Surface minimale de 5 m²
if (surface < 5) {
surfaceFacturee = 5;
prixUnitaire = 25;
} else if (surface <= 15) {
prixUnitaire = 22;
} else if (surface <= 30) {
prixUnitaire = 20;
} else if (surface <= 50) {
prixUnitaire = 18;
} else if (surface <= 100) {
prixUnitaire = 16;
} else {
prixUnitaire = 15;
}
let prixBase = surfaceFacturee * prixUnitaire;
// Calcul des suppléments
let supplements = 0;
// Suppléments pour préparation
const preparationsSelectionnees = document.querySelectorAll('input[name="preparation[]"]:checked');
preparationsSelectionnees.forEach(prep => {
switch(prep.value) {
case 'enduit':
supplements += surface * 8; // 8€/m² pour enduit
break;
case 'anti_taches':
supplements += surface * 12; // 12€/m² pour anti-taches
break;
case 'decapage':
supplements += surface * 15; // 15€/m² pour décapage
break;
case 'papier_peint':
supplements += surface * 5; // 5€/m² pour arrachage
break;
case 'rebouchage':
supplements += surface * 3; // 3€/m² pour rebouchage
break;
case 'lessivage':
supplements += surface * 2; // 2€/m² pour lessivage
break;
case 'poncage':
supplements += surface * 3; // 3€/m² pour ponçage
break;
case 'sous_couche':
supplements += surface * 4; // 4€/m² pour sous-couche
break;
case 'anti_humidite':
supplements += surface * 10; // 10€/m² pour anti-humidité
break;
case 'anti_moisissure':
supplements += surface * 6; // 6€/m² pour fongicide
break;
}
});
// Suppléments pour type de peinture
const typePeinture = document.getElementById('typePeinture').value;
switch(typePeinture) {
case 'glycero':
supplements += surface * 3;
break;
case 'anti_humidite':
supplements += surface * 8;
break;
case 'isolante':
supplements += surface * 15;
break;
case 'ecologique':
supplements += surface * 5;
break;
case 'facade':
supplements += surface * 10;
break;
case 'sol':
supplements += surface * 12;
break;
}
// Supplément couleurs multiples
const couleurs = document.getElementById('couleurs').value;
if (couleurs === '2') supplements += surface * 2;
else if (couleurs === '3') supplements += surface * 4;
else if (couleurs === '4+') supplements += surface * 6;
else if (couleurs === 'teinte_specifique') supplements += surface * 8;
// Supplément urgence
const urgence = document.getElementById('urgence').value;
if (urgence === 'urgent') supplements += prixBase * 0.2; // +20%
else if (urgence === 'tres_urgent') supplements += prixBase * 0.5; // +50%
const totalHT = prixBase + supplements;
const totalTTC = totalHT * 1.1; // TVA 10%
// Affichage
document.getElementById('prixBase').textContent = prixBase.toFixed(0) + '€';
document.getElementById('supplementsTotal').textContent = supplements.toFixed(0) + '€';
document.getElementById('totalHT').textContent = totalHT.toFixed(0) + '€';
document.getElementById('totalTTC').textContent = totalTTC.toFixed(0) + '€';
}
// Event listeners pour recalcul automatique
['longueur', 'largeur', 'hauteur', 'portes_nb', 'fenetres_nb', 'surface_manuelle'].forEach(id => {
document.getElementById(id).addEventListener('input', calculerSurface);
});
document.getElementById('typePeinture').addEventListener('change', calculerSurface);
document.getElementById('couleurs').addEventListener('change', calculerSurface);
document.getElementById('urgence').addEventListener('change', calculerSurface);
document.querySelectorAll('input[name="preparation[]"]').forEach(checkbox => {
checkbox.addEventListener('change', calculerSurface);
});
document.querySelectorAll('input[name="surfaces[]"]').forEach(checkbox => {
checkbox.addEventListener('change', calculerSurface);
});
// Gestion du formulaire
document.getElementById('devisForm').addEventListener('submit', function(e) {
e.preventDefault();
// Récupération des données
const formData = new FormData(this);
const data = {};
for (let [key, value] of formData.entries()) {
if (data[key]) {
if (Array.isArray(data[key])) {
data[key].push(value);
} else {
data[key] = [data[key], value];
}
} else {
data[key] = value;
}
}
// Ajout automatique de la date de création
const now = new Date();
data.Date_Creation_Client = now.toLocaleDateString('fr-FR');
// Génération d'un ID client unique (basé sur la date/heure)
data.Id_Client = 'CLI_' + now.getFullYear() +
String(now.getMonth() + 1).padStart(2, '0') +
String(now.getDate()).padStart(2, '0') + '_' +
String(now.getHours()).padStart(2, '0') +
String(now.getMinutes()).padStart(2, '0');
// Affichage des résultats (ici vous pourriez envoyer à votre système)
const resumeClient = data.Type_Client === 'Entreprise' ?
`${data.Nom_Client} (Contact: ${data.Nom_contact || 'Non renseigné'})` :
data.Nom_Client;
alert('Devis généré avec succès !\n\n' +
'🆔 ID Client: ' + data.Id_Client + '\n' +
'📅 Date: ' + data.Date_Creation_Client + '\n' +
'Type: ' + data.Type_Client + '\n' +
'Client: ' + resumeClient +
(data.Siret_Client ? '\nSIRET: ' + data.Siret_Client : '') +
(data.Reference_Dossier ? '\nRéférence: ' + data.Reference_Dossier : '') +
(selectedEntreprise ? '\n🤖 Données récupérées automatiquement (système multi-API)' : '') +
'\nAdresse client: ' + data.Adresse_Client +
'\nAdresse chantier: ' + data.Adresse_Chantier +
'\nSurface: ' + document.getElementById('surfaceTotal').textContent +
'\nTotal TTC: ' + document.getElementById('totalTTC').textContent +
'\n\n✅ Données prêtes pour export vers Google Sheets !' +
'\n📋 Correspondance parfaite avec vos colonnes :\n' +
'- Id_Client ✓ Type_Client ✓ Nom_Client ✓\n' +
'- Nom_contact ✓ Adresse_Client ✓ Adresse_Chantier ✓\n' +
'- Reference_Dossier ✓ Telephone_Client ✓ Email_Client ✓\n' +
'- Siret_Client ✓ Date_Creation_Client ✓');
});
// Calcul initial et initialisation
gererTypeClient(); // Initialiser l'affichage des champs client
initCopieAdresse(); // Initialiser la gestion des adresses
initServicesSelection(); // Initialiser la sélection des services