feat(v2.0.3): Marchés hybrides et améliorations multiples
Fonctionnalités principales : 1. Marchés hybrides - Onglet Mercurial - Ajout onglet Mercurial avec style distinct (vert, gras, blanc) - Affichage des produits mercuriaux pour marchés hybrides - Filtrage automatique des produits "Hors Marché 999" - Documentation Phase 2 avec CAS 1 et CAS 2 de marchés hybrides - Règles métier pour validation différenciée (devis 100% mercurial vs mixte) 2. Corrections bugs - Fix flag chkChange sur onglet "Sélection Produits" (callback asynchrone) - Plus d'alerte intempestive après sauvegarde des produits 3. Outils de déploiement - Nouveau script deploy-file.sh pour déploiement unitaire (DEV/PROD) - Amélioration deploy-cleo.sh 4. Gestion multi-contacts (v2.0.3) - Contrôleur AJAX cjxcontacts.php - Script migration clients_contacts - Documentation complète 5. Documentation - Mise à jour TODO.md avec Phase 2 marchés hybrides - Mise à jour README.md v2.0.3 - Ajout RULES.md - Ajout migration_clients_contacts.sql 6. Nettoyage - Suppression fichiers obsolètes (conf_new.php, conf_old.php, uof_linet_20250911.sql) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
245
controllers/cjxcontacts.php
Normal file
245
controllers/cjxcontacts.php
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
//! Page des requêtes AJAX pour la gestion des contacts clients
|
||||
|
||||
global $Session;
|
||||
global $Route;
|
||||
|
||||
$fk_user = $Session->_user["rowid"];
|
||||
|
||||
switch ($Route->_action) {
|
||||
case "load_contacts":
|
||||
// Charge tous les contacts d'un client
|
||||
$data = json_decode(file_get_contents("php://input"));
|
||||
if (isset($data->fk_client)) {
|
||||
$fk_client = nettoie_input($data->fk_client);
|
||||
$fkClientSafe = intval($fk_client);
|
||||
|
||||
try {
|
||||
$db = Database::getInstance();
|
||||
$sql = 'SELECT rowid, nom, prenom, fonction, telephone, mobile, email, principal, active
|
||||
FROM clients_contacts
|
||||
WHERE fk_client = :fk_client AND active = 1
|
||||
ORDER BY principal DESC, nom, prenom';
|
||||
$contacts = $db->fetchAll($sql, [':fk_client' => $fkClientSafe]);
|
||||
echo json_encode($contacts);
|
||||
} catch (Exception $e) {
|
||||
error_log("Erreur load_contacts : " . $e->getMessage());
|
||||
echo json_encode(array('ret' => 'ko', 'msg' => 'Erreur lors du chargement des contacts'));
|
||||
}
|
||||
} else {
|
||||
echo json_encode(array('ret' => 'ko', 'msg' => 'Client non spécifié'));
|
||||
}
|
||||
break;
|
||||
|
||||
case "load_contact":
|
||||
// Charge un contact spécifique
|
||||
$data = json_decode(file_get_contents("php://input"));
|
||||
if (isset($data->rowid)) {
|
||||
$rowid = nettoie_input($data->rowid);
|
||||
$rowidSafe = intval($rowid);
|
||||
|
||||
try {
|
||||
$db = Database::getInstance();
|
||||
$sql = 'SELECT rowid, fk_client, nom, prenom, fonction, telephone, mobile, email, principal, active
|
||||
FROM clients_contacts
|
||||
WHERE rowid = :rowid';
|
||||
$contact = $db->fetchAll($sql, [':rowid' => $rowidSafe]);
|
||||
if (count($contact) == 1) {
|
||||
echo json_encode($contact[0]);
|
||||
} else {
|
||||
echo json_encode(array('ret' => 'ko', 'msg' => 'Contact introuvable'));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("Erreur load_contact : " . $e->getMessage());
|
||||
echo json_encode(array('ret' => 'ko', 'msg' => 'Erreur lors du chargement du contact'));
|
||||
}
|
||||
} else {
|
||||
echo json_encode(array('ret' => 'ko', 'msg' => 'Contact non spécifié'));
|
||||
}
|
||||
break;
|
||||
|
||||
case "save_contact":
|
||||
// Crée ou met à jour un contact
|
||||
if ($_POST) {
|
||||
$rowid = nettoie_input($_POST["rowid"]);
|
||||
$fk_client = nettoie_input($_POST["fk_client"]);
|
||||
$nom = nettoie_input($_POST["nom"]);
|
||||
$prenom = nettoie_input($_POST["prenom"]);
|
||||
$fonction = nettoie_input($_POST["fonction"]);
|
||||
$telephone = formattel(nettoie_input($_POST["telephone"]));
|
||||
$mobile = formattel(nettoie_input($_POST["mobile"]));
|
||||
$email = nettoie_input($_POST["email"]);
|
||||
|
||||
$principal = 0;
|
||||
if (isset($_POST["principal"]) && $_POST["principal"] == "1") {
|
||||
$principal = 1;
|
||||
}
|
||||
|
||||
$fkClientSafe = intval($fk_client);
|
||||
$fkUserSafe = intval($fk_user);
|
||||
|
||||
try {
|
||||
$db = Database::getInstance();
|
||||
|
||||
if ($rowid == 0) {
|
||||
// Création d'un nouveau contact
|
||||
// Si ce contact est marqué comme principal, on retire le flag principal des autres contacts du client
|
||||
if ($principal == 1) {
|
||||
$sqlUpdate = 'UPDATE clients_contacts SET principal = 0 WHERE fk_client = :fk_client';
|
||||
$db->query($sqlUpdate, [':fk_client' => $fkClientSafe]);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'fk_client' => $fkClientSafe,
|
||||
'nom' => $nom,
|
||||
'prenom' => $prenom,
|
||||
'fonction' => $fonction,
|
||||
'telephone' => $telephone,
|
||||
'mobile' => $mobile,
|
||||
'email' => $email,
|
||||
'principal' => $principal,
|
||||
'active' => 1,
|
||||
'date_creat' => date("Y-m-d H:i:s"),
|
||||
'fk_user_creat' => $fkUserSafe
|
||||
];
|
||||
|
||||
$newId = $db->insert('clients_contacts', $data);
|
||||
eLog("Contact créé avec l'ID : " . $newId);
|
||||
echo json_encode(array('ret' => 'ok', 'msg' => 'Contact créé avec succès', 'rowid' => $newId));
|
||||
|
||||
} else {
|
||||
// Mise à jour d'un contact existant
|
||||
$rowidSafe = intval($rowid);
|
||||
|
||||
// Si ce contact est marqué comme principal, on retire le flag principal des autres contacts du client
|
||||
if ($principal == 1) {
|
||||
$sqlUpdate = 'UPDATE clients_contacts SET principal = 0 WHERE fk_client = :fk_client AND rowid != :rowid';
|
||||
$db->query($sqlUpdate, [':fk_client' => $fkClientSafe, ':rowid' => $rowidSafe]);
|
||||
}
|
||||
|
||||
$sql = 'UPDATE clients_contacts
|
||||
SET nom = :nom, prenom = :prenom, fonction = :fonction, telephone = :telephone,
|
||||
mobile = :mobile, email = :email, principal = :principal,
|
||||
date_modif = :date_modif, fk_user_modif = :fk_user_modif
|
||||
WHERE rowid = :rowid';
|
||||
$params = [
|
||||
':nom' => $nom,
|
||||
':prenom' => $prenom,
|
||||
':fonction' => $fonction,
|
||||
':telephone' => $telephone,
|
||||
':mobile' => $mobile,
|
||||
':email' => $email,
|
||||
':principal' => $principal,
|
||||
':date_modif' => date("Y-m-d H:i:s"),
|
||||
':fk_user_modif' => $fkUserSafe,
|
||||
':rowid' => $rowidSafe
|
||||
];
|
||||
|
||||
$db->query($sql, $params);
|
||||
eLog("Contact mis à jour : " . $rowidSafe);
|
||||
echo json_encode(array('ret' => 'ok', 'msg' => 'Contact mis à jour avec succès', 'rowid' => $rowidSafe));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("Erreur save_contact : " . $e->getMessage());
|
||||
echo json_encode(array('ret' => 'ko', 'msg' => 'Erreur lors de l\'enregistrement du contact'));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case "delete_contact":
|
||||
// Supprime (désactive) un contact
|
||||
$data = json_decode(file_get_contents("php://input"));
|
||||
if (isset($data->rowid)) {
|
||||
$rowid = nettoie_input($data->rowid);
|
||||
$rowidSafe = intval($rowid);
|
||||
|
||||
try {
|
||||
$db = Database::getInstance();
|
||||
|
||||
// Vérifier qu'il reste au moins un autre contact actif pour ce client
|
||||
$sqlCheck = 'SELECT cc.fk_client, COUNT(*) as nb_contacts
|
||||
FROM clients_contacts cc
|
||||
WHERE cc.rowid = :rowid';
|
||||
$result = $db->fetchAll($sqlCheck, [':rowid' => $rowidSafe]);
|
||||
|
||||
if (count($result) == 1) {
|
||||
$fkClient = $result[0]['fk_client'];
|
||||
|
||||
// Compter les contacts actifs restants
|
||||
$sqlCount = 'SELECT COUNT(*) as nb FROM clients_contacts WHERE fk_client = :fk_client AND active = 1 AND rowid != :rowid';
|
||||
$countResult = $db->fetchAll($sqlCount, [':fk_client' => $fkClient, ':rowid' => $rowidSafe]);
|
||||
|
||||
if ($countResult[0]['nb'] == 0) {
|
||||
echo json_encode(array('ret' => 'ko', 'msg' => 'Impossible de supprimer le dernier contact actif du client'));
|
||||
} else {
|
||||
// Désactiver le contact
|
||||
$fkUserSafe = intval($fk_user);
|
||||
$sql = 'UPDATE clients_contacts
|
||||
SET active = 0, date_modif = :date_modif, fk_user_modif = :fk_user_modif
|
||||
WHERE rowid = :rowid';
|
||||
$params = [
|
||||
':date_modif' => date("Y-m-d H:i:s"),
|
||||
':fk_user_modif' => $fkUserSafe,
|
||||
':rowid' => $rowidSafe
|
||||
];
|
||||
|
||||
$db->query($sql, $params);
|
||||
eLog("Contact désactivé : " . $rowidSafe);
|
||||
echo json_encode(array('ret' => 'ok', 'msg' => 'Contact supprimé avec succès'));
|
||||
}
|
||||
} else {
|
||||
echo json_encode(array('ret' => 'ko', 'msg' => 'Contact introuvable'));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
error_log("Erreur delete_contact : " . $e->getMessage());
|
||||
echo json_encode(array('ret' => 'ko', 'msg' => 'Erreur lors de la suppression du contact'));
|
||||
}
|
||||
} else {
|
||||
echo json_encode(array('ret' => 'ko', 'msg' => 'Contact non spécifié'));
|
||||
}
|
||||
break;
|
||||
|
||||
case "set_principal":
|
||||
// Définit un contact comme principal
|
||||
$data = json_decode(file_get_contents("php://input"));
|
||||
if (isset($data->rowid) && isset($data->fk_client)) {
|
||||
$rowid = nettoie_input($data->rowid);
|
||||
$fk_client = nettoie_input($data->fk_client);
|
||||
$rowidSafe = intval($rowid);
|
||||
$fkClientSafe = intval($fk_client);
|
||||
|
||||
try {
|
||||
$db = Database::getInstance();
|
||||
$fkUserSafe = intval($fk_user);
|
||||
|
||||
// Retirer le flag principal de tous les contacts du client
|
||||
$sqlReset = 'UPDATE clients_contacts SET principal = 0 WHERE fk_client = :fk_client';
|
||||
$db->query($sqlReset, [':fk_client' => $fkClientSafe]);
|
||||
|
||||
// Définir le contact comme principal
|
||||
$sql = 'UPDATE clients_contacts
|
||||
SET principal = 1, date_modif = :date_modif, fk_user_modif = :fk_user_modif
|
||||
WHERE rowid = :rowid';
|
||||
$params = [
|
||||
':date_modif' => date("Y-m-d H:i:s"),
|
||||
':fk_user_modif' => $fkUserSafe,
|
||||
':rowid' => $rowidSafe
|
||||
];
|
||||
|
||||
$db->query($sql, $params);
|
||||
eLog("Contact principal défini : " . $rowidSafe);
|
||||
echo json_encode(array('ret' => 'ok', 'msg' => 'Contact principal défini avec succès'));
|
||||
} catch (Exception $e) {
|
||||
error_log("Erreur set_principal : " . $e->getMessage());
|
||||
echo json_encode(array('ret' => 'ko', 'msg' => 'Erreur lors de la définition du contact principal'));
|
||||
}
|
||||
} else {
|
||||
echo json_encode(array('ret' => 'ko', 'msg' => 'Données manquantes'));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
echo json_encode(array('ret' => 'ko', 'msg' => 'Action inconnue'));
|
||||
break;
|
||||
}
|
||||
exit();
|
||||
@@ -54,7 +54,7 @@ switch ($Route->_action) {
|
||||
|
||||
//! 4. On met à jour la date_demande, date_remise, num_opportunite et fk_statut_devis du nouveau devis
|
||||
$newRowidSafe = intval($newRowid);
|
||||
$sql = 'UPDATE devis SET date_demande = "' . date("Y-m-d H:i:s") . '", date_remise = "", num_opportunite = "", fk_statut_devis = 1 WHERE rowid = ' . $newRowidSafe . ';';
|
||||
$sql = 'UPDATE devis SET date_demande = "' . date("Y-m-d H:i:s") . '", date_remise = NULL, num_opportunite = "", fk_statut_devis = 1 WHERE rowid = ' . $newRowidSafe . ';';
|
||||
eLog($sql);
|
||||
qSQL($sql, "gen");
|
||||
|
||||
@@ -124,14 +124,16 @@ switch ($Route->_action) {
|
||||
$sql = 'UPDATE devis SET chk_maj = 0 WHERE rowid = ' . $cidSafe . ';';
|
||||
qSQL($sql, "gen");
|
||||
}
|
||||
$sql = 'SELECT d.rowid, d.fk_user, d.fk_client, d.fk_marche, m.libelle AS lib_marche, d.fk_statut_devis, d.dossier, d.num_opportunite, d.montant_total_ht, ';
|
||||
$sql = 'SELECT d.rowid, d.fk_user, d.fk_client, d.fk_contact, d.fk_marche, m.libelle AS lib_marche, d.fk_statut_devis, d.dossier, d.num_opportunite, d.montant_total_ht, ';
|
||||
$sql .= 'd.date_demande, d.date_remise, d.montant_total_ht_remise, d.marge_totale, d.commentaire, d.comment_devis, d.chk_clients_secteur, d.chk_speciaux, ';
|
||||
$sql .= 'd.lib_new_client, d.type_new_client, d.adresse1_new_client, d.adresse2_new_client, d.adresse3_new_client, d.cp_new_client, d.ville_new_client,';
|
||||
$sql .= 'd.contact_new_nom, d.contact_new_prenom, d.contact_new_fonction, d.new_telephone, d.new_mobile, d.new_email, ';
|
||||
$sql .= 'd.comment_geste_comm, d.comment_validat, d.chk_validat, d.fk_user_validat, d.date_validat, ';
|
||||
$sql .= 'xs.libelle as lib_statut_devis, c.code, c.libelle, c.adresse1, c.adresse2, c.adresse3, c.cp, c.ville, c.type_client, ';
|
||||
$sql .= 'c.contact_nom, c.contact_prenom, c.contact_fonction, c.telephone, c.mobile, c.email, d.chk_devis_photos ';
|
||||
$sql .= 'FROM devis d LEFT JOIN clients c ON d.fk_client = c.rowid LEFT JOIN x_statuts_devis xs ON d.fk_statut_devis = xs.rowid ';
|
||||
$sql .= 'cc.rowid as contact_rowid, cc.nom as contact_nom, cc.prenom as contact_prenom, cc.fonction as contact_fonction, cc.telephone, cc.mobile, cc.email, d.chk_devis_photos ';
|
||||
$sql .= 'FROM devis d LEFT JOIN clients c ON d.fk_client = c.rowid ';
|
||||
$sql .= 'LEFT JOIN clients_contacts cc ON d.fk_contact = cc.rowid ';
|
||||
$sql .= 'LEFT JOIN x_statuts_devis xs ON d.fk_statut_devis = xs.rowid ';
|
||||
$sql .= 'LEFT JOIN marches m ON d.fk_marche = m.rowid ';
|
||||
$sql .= 'WHERE d.rowid = ' . $cidSafe . ';';
|
||||
echo getinfos($sql, "gen", "json");
|
||||
@@ -162,7 +164,7 @@ switch ($Route->_action) {
|
||||
if (isset($data->secteur)) {
|
||||
$chkSecteur = nettoie_input($data->secteur);
|
||||
$fkUser = nettoie_input($data->user);
|
||||
$sql = 'SELECT rowid, libelle, CONCAT(libelle, ", ", adresse1, ", ", cp, " ", ville) AS rech, adresse1, adresse2, adresse3, cp, ville, contact_nom, contact_prenom, contact_fonction, telephone, mobile, email, type_client FROM clients WHERE active=1 ';
|
||||
$sql = 'SELECT rowid, code, libelle, CONCAT(libelle, ", ", adresse1, ", ", cp, " ", ville) AS rech, adresse1, adresse2, adresse3, cp, ville, contact_nom, contact_prenom, contact_fonction, telephone, mobile, email, type_client FROM clients WHERE active=1 ';
|
||||
if ($chkSecteur == "1") {
|
||||
//! on ne prend que les clients du secteur de l'utilisateur
|
||||
$fkUserSafe = intval($fkUser);
|
||||
@@ -197,6 +199,32 @@ switch ($Route->_action) {
|
||||
}
|
||||
break;
|
||||
|
||||
case "load_produits_mercurial":
|
||||
//! Charge les produits du marché hybride pour l'onglet Mercurial
|
||||
$data = json_decode(file_get_contents("php://input"));
|
||||
if (isset($data->fk_marche)) {
|
||||
$fkMarche = nettoie_input($data->fk_marche);
|
||||
$fkMarcheSafe = intval($fkMarche);
|
||||
|
||||
// Vérifier que le marché est bien hybride
|
||||
$sql = 'SELECT chk_marche_hybride FROM marches WHERE rowid = ' . $fkMarcheSafe . ';';
|
||||
$retSql = getinfos($sql, "gen");
|
||||
|
||||
if (count($retSql) == 1 && $retSql[0]["chk_marche_hybride"] == 1) {
|
||||
// Le marché est hybride, on charge tous les produits de ce marché (hors 999)
|
||||
$sql = 'SELECT p.*, CONCAT(p.code, " - ", p.libelle) AS rech, pf.fk_famille, xf.libelle AS lib_famille ';
|
||||
$sql .= 'FROM produits p LEFT JOIN produits_familles pf ON p.groupe=pf.groupe LEFT JOIN x_familles xf on pf.fk_famille = xf.rowid ';
|
||||
$sql .= 'WHERE p.fk_marche = ' . $fkMarcheSafe . ' AND p.fk_marche != 999 AND p.active=1 ORDER BY xf.ordre, pf.ordre;';
|
||||
echo getinfos($sql, "gen", "json");
|
||||
} else {
|
||||
// Le marché n'est pas hybride, on retourne un tableau vide
|
||||
echo json_encode(array());
|
||||
}
|
||||
} else {
|
||||
echo json_encode(array());
|
||||
}
|
||||
break;
|
||||
|
||||
case "load_devis_marche_produits":
|
||||
//! Charge les produits enregistrés pour un marché
|
||||
$data = json_decode(file_get_contents("php://input"));
|
||||
@@ -234,7 +262,7 @@ switch ($Route->_action) {
|
||||
|
||||
$sql = 'SELECT p.*, CONCAT(p.code, " - ", p.libelle) AS rech, pf.fk_famille, xf.libelle AS lib_famille, "0" AS chk_prix_net ';
|
||||
$sql .= 'FROM produits p LEFT JOIN produits_familles pf ON p.groupe=pf.groupe LEFT JOIN x_familles xf on pf.fk_famille = xf.rowid ';
|
||||
$sql .= 'WHERE p.fk_marche = ' . $cidSafe . ' AND p.active=1 ORDER BY xf.ordre, pf.ordre;';
|
||||
$sql .= 'WHERE p.fk_marche = ' . intval($cid) . ' AND p.active=1 ORDER BY xf.ordre, pf.ordre;';
|
||||
$upls = getinfos($sql, "gen");
|
||||
|
||||
if ($cid != "999") {
|
||||
@@ -390,31 +418,13 @@ switch ($Route->_action) {
|
||||
$commentaire = nettoie_input($_POST["commentaire"]);
|
||||
$newCommentaire = 0;
|
||||
|
||||
$contact_nom = nettoie_input($_POST["contact_nom"]);
|
||||
$contact_prenom = nettoie_input($_POST["contact_prenom"]);
|
||||
$contact_fonction = nettoie_input($_POST["contact_fonction"]);
|
||||
$email = nettoie_input($_POST["email"]);
|
||||
$telephone = formattel(nettoie_input($_POST["telephone"]));
|
||||
$mobile = formattel(nettoie_input($_POST["mobile"]));
|
||||
// Récupération du contact sélectionné
|
||||
$fk_contact = isset($_POST["fk_contact"]) ? intval($_POST["fk_contact"]) : 0;
|
||||
if ($fk_contact == 0) $fk_contact = NULL;
|
||||
|
||||
$set = 'fk_client=' . $fk_client . ', num_opportunite="' . $num_opportunite . '", date_demande="' . $date_demande . '", date_remise="' . $date_remise . '", ';
|
||||
$set = 'fk_client=' . $fk_client . ', fk_contact=' . ($fk_contact === NULL ? 'NULL' : $fk_contact) . ', num_opportunite="' . $num_opportunite . '", date_demande="' . $date_demande . '", date_remise="' . $date_remise . '", ';
|
||||
$set .= 'fk_user=' . $fk_user . ', fk_marche=' . $fk_marche . ', commentaire="' . $commentaire . '", chk_devis_photos=' . $chk_devis_photos . ', ';
|
||||
|
||||
if ($fk_client == 0) {
|
||||
//! C'est un nouveau client : on enregistre ces infos et celle du contact dans le devis et non au niveau de la table clients
|
||||
$libNewClient = nettoie_input($_POST["lib_client"]);
|
||||
$typNewClient = nettoie_input($_POST["type_client"]);
|
||||
$adr1NewClient = nettoie_input($_POST["adresse1"]);
|
||||
$adr2NewClient = nettoie_input($_POST["adresse2"]);
|
||||
$adr3NewClient = nettoie_input($_POST["adresse3"]);
|
||||
$cpNewClient = nettoie_input($_POST["cp"]);
|
||||
// Si le CP a une longueur de 4, on rajoute un 0 devant
|
||||
if (strlen($cpNewClient) == 4) $cpNewClient = "0" . $cpNewClient;
|
||||
$villeNewClient = nettoie_input($_POST["ville"]);
|
||||
$set .= 'lib_new_client="' . $libNewClient . '", type_new_client="' . $typNewClient . '", adresse1_new_client="' . $adr1NewClient . '", adresse2_new_client="' . $adr2NewClient . '", adresse3_new_client="' . $adr3NewClient . '", cp_new_client="' . $cpNewClient . '", ville_new_client="' . $villeNewClient . '", ';
|
||||
$set .= 'contact_new_nom="' . $contact_nom . '", contact_new_prenom="' . $contact_prenom . '", contact_new_fonction="' . $contact_fonction . '", new_email="' . $email . '", new_telephone="' . $telephone . '", new_mobile="' . $mobile . '", ';
|
||||
}
|
||||
|
||||
if ($_POST["rowid"] == 0) {
|
||||
//! C'est un nouveau devis
|
||||
//! On le range dans un dossier
|
||||
@@ -465,14 +475,8 @@ switch ($Route->_action) {
|
||||
}
|
||||
eLog('Entete Devis Save : ' . $sql);
|
||||
|
||||
if ($fk_client != "0") {
|
||||
//! On sauvegarde aussi les infos complémentaires du client qui peuvent ête mises à jour
|
||||
$sql = 'UPDATE clients SET contact_nom="' . $contact_nom . '", contact_prenom="' . $contact_prenom . '", contact_fonction="' . $contact_fonction . '", ';
|
||||
$fkClientSafe = intval($fk_client);
|
||||
$sql .= 'email="' . $email . '", telephone="' . $telephone . '", mobile="' . $mobile . '" WHERE rowid=' . $fkClientSafe . ';';
|
||||
eLog('Entete Devis Save infos client : ' . $sql);
|
||||
qSQL($sql, "gen");
|
||||
}
|
||||
// NOTE: Les contacts sont maintenant gérés via la table clients_contacts
|
||||
// et non plus directement dans la table clients
|
||||
|
||||
// On inscrit l'enregistrement dans le journal si il y a eu un changement de commentaire ou bien si c'est une création avec commentaire
|
||||
if ($newCommentaire > 0) {
|
||||
@@ -651,11 +655,8 @@ switch ($Route->_action) {
|
||||
try {
|
||||
$db = Database::getInstance();
|
||||
$sql = 'SELECT rowid, code, libelle, prix_vente FROM produits WHERE active=1 AND (code LIKE :term OR libelle LIKE :term) ORDER BY code';
|
||||
$stmt = $db->prepare($sql);
|
||||
$termParam = '%' . $term . '%';
|
||||
$stmt->bindParam(':term', $termParam, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
$upls = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$upls = $db->fetchAll($sql, [':term' => $termParam]);
|
||||
} catch (Exception $e) {
|
||||
error_log("Erreur recherche produits : " . $e->getMessage());
|
||||
$upls = [];
|
||||
@@ -1303,5 +1304,69 @@ switch ($Route->_action) {
|
||||
echo json_encode(array("success" => "true", "message" => "Devis refusé avec succès"));
|
||||
}
|
||||
break;
|
||||
|
||||
case "save_new_client":
|
||||
$data = json_decode(file_get_contents("php://input"));
|
||||
if (isset($data->libelle)) {
|
||||
try {
|
||||
$db = Database::getInstance();
|
||||
|
||||
$libelle = nettoie_input($data->libelle);
|
||||
$typeClient = nettoie_input($data->type_client);
|
||||
$adresse1 = nettoie_input($data->adresse1);
|
||||
$adresse2 = nettoie_input($data->adresse2);
|
||||
$adresse3 = nettoie_input($data->adresse3);
|
||||
$cp = nettoie_input($data->cp);
|
||||
if (strlen($cp) == 4) $cp = "0" . $cp;
|
||||
$ville = nettoie_input($data->ville);
|
||||
$fkUserSafe = intval($fk_user);
|
||||
|
||||
$sqlMaxCode = 'SELECT MAX(code) as max_code FROM clients';
|
||||
$resultCode = $db->fetchOne($sqlMaxCode);
|
||||
$newCode = ($resultCode && $resultCode['max_code']) ? intval($resultCode['max_code']) + 1 : 1;
|
||||
|
||||
$sql = 'INSERT INTO clients SET code = :code, libelle = :libelle, type_client = :type_client, adresse1 = :adresse1, adresse2 = :adresse2, adresse3 = :adresse3, ';
|
||||
$sql .= 'cp = :cp, ville = :ville, fk_user_creat = :fk_user_creat, date_creat = NOW(), active = 1';
|
||||
|
||||
$params = [
|
||||
':code' => $newCode,
|
||||
':libelle' => $libelle,
|
||||
':type_client' => $typeClient,
|
||||
':adresse1' => $adresse1,
|
||||
':adresse2' => $adresse2,
|
||||
':adresse3' => $adresse3,
|
||||
':cp' => $cp,
|
||||
':ville' => $ville,
|
||||
':fk_user_creat' => $fkUserSafe
|
||||
];
|
||||
|
||||
$db->query($sql, $params);
|
||||
$newClientId = $db->lastInsertId();
|
||||
|
||||
if ($newClientId > 0) {
|
||||
$sql = 'INSERT INTO clients_contacts SET fk_client = :fk_client, nom = :nom, prenom = :prenom, principal = 1, active = 1, date_creat = NOW()';
|
||||
|
||||
$params = [
|
||||
':fk_client' => $newCode,
|
||||
':nom' => 'À compléter',
|
||||
':prenom' => ''
|
||||
];
|
||||
|
||||
$db->query($sql, $params);
|
||||
|
||||
eLog("Nouveau client créé : ID=" . $newClientId . ", code=" . $newCode);
|
||||
echo json_encode(array("success" => true, "rowid" => $newClientId, "code" => $newCode, "message" => "Client créé avec succès"));
|
||||
} else {
|
||||
eLog("save_new_client ERREUR: newClientId = 0");
|
||||
echo json_encode(array("success" => false, "message" => "Erreur lors de la création du client - ID non récupéré"));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$errorMsg = $e->getMessage();
|
||||
error_log("Erreur création client : " . $errorMsg);
|
||||
eLog("save_new_client EXCEPTION: " . $errorMsg);
|
||||
echo json_encode(array("success" => false, "message" => "Erreur : " . $errorMsg));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
exit();
|
||||
|
||||
@@ -140,10 +140,7 @@ switch ($Route->_action) {
|
||||
try {
|
||||
$db = Database::getInstance();
|
||||
$sql = 'SELECT c.* FROM clients c WHERE c.code = :code';
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->bindParam(':code', $code, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
$record = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$record = $db->fetchAll($sql, [':code' => $code]);
|
||||
} catch (Exception $e) {
|
||||
error_log("Erreur recherche client : " . $e->getMessage());
|
||||
$record = [];
|
||||
@@ -155,8 +152,7 @@ switch ($Route->_action) {
|
||||
$db = Database::getInstance();
|
||||
$sql = 'INSERT INTO clients SET code = :code, libelle = :libelle, siret = :siret, adresse1 = :adresse1, adresse2 = :adresse2, adresse3 = :adresse3, cp = :cp, ville = :ville, ';
|
||||
$sql .= 'type_client = :type_client, contact_nom = :contact_nom, contact_prenom = :contact_prenom, contact_fonction = :contact_fonction, telephone = :telephone, mobile = :mobile, email = :email, chk_import = 1';
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute([
|
||||
$stmt = $db->query($sql, [
|
||||
':code' => $code,
|
||||
':libelle' => $libelle,
|
||||
':siret' => $siret,
|
||||
@@ -198,8 +194,7 @@ switch ($Route->_action) {
|
||||
$sql = 'UPDATE clients SET libelle = :libelle, siret = :siret, adresse1 = :adresse1, adresse2 = :adresse2, adresse3 = :adresse3, cp = :cp, ville = :ville, ';
|
||||
$sql .= 'type_client = :type_client, contact_nom = :contact_nom, contact_prenom = :contact_prenom, contact_fonction = :contact_fonction, telephone = :telephone, mobile = :mobile, email = :email, chk_import = 1 ';
|
||||
$sql .= 'WHERE code = :code';
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute([
|
||||
$stmt = $db->query($sql, [
|
||||
':libelle' => $libelle,
|
||||
':siret' => $siret,
|
||||
':adresse1' => $adresse1,
|
||||
@@ -378,12 +373,18 @@ switch ($Route->_action) {
|
||||
$libelle = str_replace('"', '', trim($data[1])); // on remplace les doubles guillemets par rien
|
||||
// on réencode en ISO 8859-1 pour éviter les problèmes d'accent
|
||||
if ($codOrigin == "UTF-8") {
|
||||
$libelle = utf8_decode($libelle);
|
||||
}
|
||||
if ($codOrigin != "ISO-8859-1") {
|
||||
// Convertir en ISO 8859-1
|
||||
$libelle = iconv($codOrigin, "ISO-8859-15//IGNORE", $libelle);
|
||||
// Utiliser mb_convert_encoding au lieu de utf8_decode (déprécié en PHP 8.3)
|
||||
$libelle = mb_convert_encoding($libelle, "ISO-8859-1", "UTF-8");
|
||||
} elseif ($codOrigin == "Windows-1252" || $codOrigin == "CP1252") {
|
||||
// Windows-1252 est très proche de ISO-8859-1
|
||||
// On traite le texte tel quel car les caractères de base sont compatibles
|
||||
// Seulement quelques caractères spéciaux diffèrent (€, œ, etc.)
|
||||
$libelle = $libelle; // Pas de conversion, on garde tel quel
|
||||
} elseif ($codOrigin == "ISO-8859-15") {
|
||||
// ISO-8859-15 est compatible avec ISO-8859-1 sauf pour le symbole €
|
||||
$libelle = str_replace('€', 'EUR', $libelle);
|
||||
}
|
||||
// Pour ISO-8859-1, on ne fait rien, c'est déjà le bon format
|
||||
|
||||
$groupe = str_replace(" ", " ", trim($data[2])); // on remplace les doubles espaces par un simple espace
|
||||
$liste = trim($data[3]);
|
||||
@@ -532,7 +533,10 @@ switch ($Route->_action) {
|
||||
$ret = array('ret' => "ko", 'msg' => "Aucun fichier à importer");
|
||||
} else {
|
||||
if ($erreur == "") {
|
||||
$ret = array('ret' => "ok", 'msg' => "L'importation est terminée et s'est bien déroulée");
|
||||
$nbLignes = isset($row) ? $row - 1 : 0; // On enlève la ligne d'en-tête
|
||||
$nbMarches = isset($idMarches) ? count($idMarches) : 0;
|
||||
$msgMarches = $nbMarches > 1 ? " pour " . $nbMarches . " marchés" : ($nbMarches == 1 ? " pour 1 marché" : "");
|
||||
$ret = array('ret' => "ok", 'msg' => "Import terminé : " . $nbLignes . " produits traités" . $msgMarches);
|
||||
} else {
|
||||
$ret = array('ret' => "ko", 'msg' => $erreur);
|
||||
}
|
||||
|
||||
@@ -211,9 +211,7 @@ switch ($Route->_action) {
|
||||
$db = Database::getInstance();
|
||||
// SÉCURITÉ : Utilisation de requête préparée pour l'ID
|
||||
$sql = "SELECT `$chp` AS data FROM clients WHERE rowid = :id";
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute([':id' => intval($fk_tiers)]);
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$result = $db->fetchOne($sql, [':id' => intval($fk_tiers)]);
|
||||
if ($result) {
|
||||
$upls = $result;
|
||||
}
|
||||
@@ -290,12 +288,8 @@ switch ($Route->_action) {
|
||||
OR c.email LIKE :search
|
||||
ORDER BY c.libelle';
|
||||
|
||||
$stmt = $db->prepare($sql);
|
||||
$searchParam = '%' . $search . '%';
|
||||
$stmt->bindParam(':search', $searchParam, PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
|
||||
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$results = $db->fetchAll($sql, [':search' => $searchParam]);
|
||||
echo json_encode($results);
|
||||
} catch (Exception $e) {
|
||||
error_log("Erreur search_clients : " . $e->getMessage());
|
||||
@@ -522,16 +516,13 @@ switch ($Route->_action) {
|
||||
|
||||
// Utilisation de requêtes préparées pour la suppression
|
||||
$sql1 = 'DELETE FROM marches WHERE rowid = :id';
|
||||
$stmt1 = $db->prepare($sql1);
|
||||
$stmt1->execute(['id' => $cid]);
|
||||
$db->query($sql1, ['id' => $cid]);
|
||||
|
||||
$sql2 = 'DELETE FROM marches_listes WHERE fk_marche = :id';
|
||||
$stmt2 = $db->prepare($sql2);
|
||||
$stmt2->execute(['id' => $cid]);
|
||||
$db->query($sql2, ['id' => $cid]);
|
||||
|
||||
$sql3 = 'DELETE FROM produits WHERE fk_marche = :id';
|
||||
$stmt3 = $db->prepare($sql3);
|
||||
$stmt3->execute(['id' => $cid]);
|
||||
$db->query($sql3, ['id' => $cid]);
|
||||
|
||||
eLog("Marché supprimé : ID=$cid");
|
||||
$ret = array('ret' => "ok", 'msg' => 'Marché supprimé');
|
||||
@@ -785,9 +776,7 @@ switch ($Route->_action) {
|
||||
try {
|
||||
$db = Database::getInstance();
|
||||
$sql = 'SELECT c.code, c.libelle, c.adresse1, c.adresse2 FROM clients c WHERE c.rowid = :id';
|
||||
$stmt = $db->prepare($sql);
|
||||
$stmt->execute([':id' => intval($devis["fk_client"])]);
|
||||
$client = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$client = $db->fetchOne($sql, [':id' => intval($devis["fk_client"])]);
|
||||
if (!$client) {
|
||||
$client = ['code' => '', 'libelle' => '', 'adresse1' => '', 'adresse2' => ''];
|
||||
}
|
||||
@@ -884,8 +873,8 @@ switch ($Route->_action) {
|
||||
try {
|
||||
$db = Database::getInstance();
|
||||
$sql = 'DELETE FROM infos WHERE rowid = :id';
|
||||
$stmt = $db->prepare($sql);
|
||||
$result = $stmt->execute(['id' => $cid]);
|
||||
$stmt = $db->query($sql, ['id' => $cid]);
|
||||
$result = $stmt->rowCount() > 0;
|
||||
|
||||
if ($result) {
|
||||
eLog("Info supprimée : ID=$cid");
|
||||
|
||||
Reference in New Issue
Block a user