Initial commit: CLEO ERP avec améliorations debug
- Configuration du debug conditionnel pour dev/recette - Fonction debug() globale avec niveaux - Logging des requêtes SQL - Handlers d'exceptions et d'erreurs globaux 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
254
controllers/cjxexport.php
Normal file
254
controllers/cjxexport.php
Normal file
@@ -0,0 +1,254 @@
|
||||
<?php
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
use phpseclib3\Net\SFTP;
|
||||
|
||||
global $Route, $Session;
|
||||
$fk_user = $Session->_user['rowid'];
|
||||
|
||||
function generateXML($data) {
|
||||
$writer = new XMLWriter();
|
||||
$writer->openMemory();
|
||||
$writer->setIndent(true);
|
||||
$writer->setIndentString(' ');
|
||||
$writer->startDocument('1.0', 'UTF-8');
|
||||
|
||||
$writer->startElement('cleodevis');
|
||||
|
||||
// Éléments simples
|
||||
$simpleElements = ['id', 'opportunite', 'date_demande', 'date_remise', 'marche', 'num_marche', 'nom_marche', 'photos', 'commentaire_rr', 'speciaux', 'total_devis_ht', 'total_devis_ht_remise', 'marge_totale'];
|
||||
foreach ($simpleElements as $element) {
|
||||
$writer->writeElement($element, $data[$element]);
|
||||
}
|
||||
|
||||
// Client
|
||||
$writer->startElement('client');
|
||||
foreach ($data['client'] as $key => $value) {
|
||||
if ($key === 'contact') {
|
||||
$writer->startElement('contact');
|
||||
foreach ($value as $contactKey => $contactValue) {
|
||||
$writer->writeElement($contactKey, $contactValue);
|
||||
}
|
||||
$writer->endElement(); // contact
|
||||
} else {
|
||||
$writer->writeElement($key, $value);
|
||||
}
|
||||
}
|
||||
$writer->endElement(); // client
|
||||
|
||||
// Produits
|
||||
$writer->startElement('produits');
|
||||
foreach ($data['produits'] as $produit) {
|
||||
$writer->startElement('produit');
|
||||
$writer->writeAttribute('id', $produit['id']);
|
||||
foreach ($produit as $key => $value) {
|
||||
if ($key !== 'id') {
|
||||
$writer->writeElement($key, $value);
|
||||
}
|
||||
}
|
||||
$writer->endElement(); // produit
|
||||
}
|
||||
$writer->endElement(); // produits
|
||||
|
||||
// Produits spéciaux
|
||||
$writer->startElement('produits_speciaux');
|
||||
foreach ($data['produits_speciaux'] as $key => $value) {
|
||||
if ($key === 'produit_special') {
|
||||
foreach ($value as $produitSpecial) {
|
||||
$writer->startElement('produit_special');
|
||||
$writer->writeAttribute('id', $produitSpecial['id']);
|
||||
foreach ($produitSpecial as $psKey => $psValue) {
|
||||
if ($psKey !== 'id') {
|
||||
$writer->writeElement($psKey, $psValue);
|
||||
}
|
||||
}
|
||||
$writer->endElement(); // produit_special
|
||||
}
|
||||
} else {
|
||||
$writer->writeElement($key, $value);
|
||||
}
|
||||
}
|
||||
$writer->endElement(); // produits_speciaux
|
||||
$writer->endElement(); // cleodevis
|
||||
return $writer->outputMemory();
|
||||
}
|
||||
|
||||
function uploadToSftp($localPath, $filename) {
|
||||
eLog("Début de l'upload sur SFTP pour le fichier $localPath $filename");
|
||||
$sftp = [
|
||||
'host' => 'e1exshxstxsftp.blob.core.windows.net',
|
||||
'port' => 22,
|
||||
'username' => 'e1exshxstxsftp.edi-cleo.edicleousr',
|
||||
'password' => 'QYDavy+wIy7AoDnezPv+KC/vF+zG1q6n',
|
||||
'remote_path' => '/'
|
||||
];
|
||||
|
||||
// On va chercher le fichier XML en path absolu
|
||||
$localPath = __DIR__ . '/../' . $localPath;
|
||||
$xmlPathAndName = $localPath . DS . $filename;
|
||||
try {
|
||||
$sftp_client = new SFTP($sftp['host'], $sftp['port']);
|
||||
|
||||
if (!$sftp_client->login($sftp['username'], $sftp['password'])) {
|
||||
throw new Exception("Authentification SFTP échouée");
|
||||
}
|
||||
|
||||
$remote_file = $sftp['remote_path'] . $filename;
|
||||
|
||||
// Debug des chemins
|
||||
error_log("Chemin local absolu : " . $xmlPathAndName);
|
||||
error_log("Chemin distant : " . $remote_file);
|
||||
|
||||
// Vérification explicite du fichier
|
||||
if (!file_exists($xmlPathAndName)) {
|
||||
throw new Exception("Le fichier n'existe pas à l'emplacement : " . $xmlPathAndName);
|
||||
}
|
||||
|
||||
// Essayez d'utiliser fopen au lieu de file_get_contents
|
||||
$handle = fopen($xmlPathAndName, 'r');
|
||||
if ($handle === false) {
|
||||
throw new Exception("Impossible d'ouvrir le fichier en lecture");
|
||||
}
|
||||
|
||||
if (!$sftp_client->put($remote_file, $handle)) {
|
||||
throw new Exception("Échec de l'envoi du fichier sur le serveur distant");
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
|
||||
// Vérifiez la taille du fichier distant après l'envoi
|
||||
$remoteSize = $sftp_client->filesize($remote_file);
|
||||
if ($remoteSize === 0) {
|
||||
throw new Exception("Le fichier distant est vide après l'envoi");
|
||||
} else {
|
||||
error_log('Taille du fichier distant après l\'envoi : ' . $remoteSize);
|
||||
}
|
||||
eLog('Fichier envoyé avec succès : ' . $remote_file . ', taille sur le serveur : ' . $remoteSize);
|
||||
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
error_log("Erreur SFTP: " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch ($Route->_action) {
|
||||
case "xml_devis":
|
||||
$cid = nettoie_input($Route->_param1);
|
||||
eLog("Export XML SAP Devis : " . $cid);
|
||||
$sql = 'SELECT d.num_opportunite, d.date_demande, d.date_remise, d.fk_client, m.libelle AS lib_marche, m.numero AS num_marche, m.nom AS nom_marche, d.chk_devis_photos, d.chk_speciaux, d.commentaire AS commentaire_rr, ';
|
||||
$sql .= 'd.montant_total_ht as total_devis_ht, d.montant_total_ht_remise AS total_devis_ht_remise, d.marge_totale ';
|
||||
$sql .= 'FROM devis d LEFT JOIN marches m ON d.fk_marche=m.rowid WHERE d.rowid = ' . $cid . ';';
|
||||
$dataDevis = getinfos($sql);
|
||||
if ($dataDevis) {
|
||||
$dataDevis = $dataDevis[0];
|
||||
if ($dataDevis["fk_client"] == 0) {
|
||||
// Pas de client issu de la table clients mais un client saisi manuellement
|
||||
$sql = 'SELECT "0" AS code, d.lib_new_client AS etablissement, d.adresse1_new_client AS adresse1, d.adresse2_new_client AS adresse2, d.adresse3_new_client AS adresse3, ';
|
||||
$sql .= 'cp_new_client AS codepostal, ville_new_client AS ville FROM devis d WHERE d.rowid = ' . $cid . ';';
|
||||
$dataClient = getinfos($sql);
|
||||
$sql = 'SELECT d.contact_new_nom AS nom, d.contact_new_prenom AS prenom, d.contact_new_fonction AS fonction, d.new_telephone AS fixe, d.new_mobile AS mobile, d.new_email AS email FROM devis d WHERE d.rowid = ' . $cid . ';';
|
||||
$dataContact = getinfos($sql);
|
||||
} else {
|
||||
$sql = 'SELECT c.code, c.libelle AS etablissement, c.adresse1, c.adresse2, c.adresse3, c.cp AS codepostal, c.ville FROM clients c WHERE c.rowid = ' . $dataDevis["fk_client"] . ';';
|
||||
$dataClient = getinfos($sql);
|
||||
$sql = 'SELECT c.contact_nom AS nom, c.contact_prenom AS prenom, c.contact_fonction AS fonction, c.telephone AS fixe, c.mobile, c.email FROM clients c WHERE c.rowid = ' . $dataDevis["fk_client"] . ';';
|
||||
$dataContact = getinfos($sql);
|
||||
}
|
||||
$dataClient = $dataClient[0];
|
||||
// On ajoute l'array contact dans l'array client
|
||||
$dataClient['contact'] = $dataContact[0];
|
||||
|
||||
$sql = 'SELECT dp.fk_produit AS id, dp.code, dp.libelle AS designation, dp.prix_vente, dp.qte AS quantite, dp.remise, dp.pu_vente_remise AS pu_vente_avec_remise, dp.totalht AS total_ht, dp.marge, dp.commentaire ';
|
||||
$sql .= 'FROM devis_produits dp WHERE dp.fk_devis = ' . $cid . ' ORDER BY dp.ordre;';
|
||||
$dataProduits = getinfos($sql);
|
||||
|
||||
// $sql = 'SELECT fk_product, qty, prix_unitaire, remise, total_ht, total_ttc FROM lignes_speciales WHERE fk_devis = $cid';
|
||||
$dataProduitsSpeciaux = array(); // getinfos($sql);
|
||||
|
||||
$data = [
|
||||
'id' => $cid,
|
||||
'opportunite' => $dataDevis['num_opportunite'],
|
||||
'date_demande' => $dataDevis['date_demande'],
|
||||
'date_remise' => $dataDevis['date_remise'],
|
||||
'marche' => $dataDevis['lib_marche'],
|
||||
'num_marche' => $dataDevis['num_marche'],
|
||||
'nom_marche' => $dataDevis['nom_marche'],
|
||||
'photos' => $dataDevis['chk_devis_photos'],
|
||||
'commentaire_rr' => $dataDevis['commentaire_rr'],
|
||||
'speciaux' => $dataDevis['chk_speciaux'],
|
||||
'total_devis_ht' => $dataDevis['total_devis_ht'],
|
||||
'total_devis_ht_remise' => $dataDevis['total_devis_ht_remise'],
|
||||
'marge_totale' => $dataDevis['marge_totale'],
|
||||
'client' => $dataClient,
|
||||
'produits' => $dataProduits,
|
||||
'produits_speciaux' => $dataProduitsSpeciaux
|
||||
];
|
||||
|
||||
// ob_start();
|
||||
// $xmlName = 'dv' . $cid . '_' . date("Y_m_d_H_i") . '.xml';
|
||||
// $xml = generateXML($data);
|
||||
// ob_end_clean();
|
||||
|
||||
// $xmlPath = 'pub/files/upload/devis';
|
||||
// $xmlPathAndName = $xmlPath . DS . $xmlName;
|
||||
// file_put_contents($xmlPathAndName, $xml);
|
||||
|
||||
|
||||
// Définition des chemins
|
||||
$xmlName = 'dv' . $cid . '_' . date("Y_m_d_H_i") . '.xml';
|
||||
$xmlPath = 'pub/files/upload/devis';
|
||||
$xmlPathAndName = $xmlPath . DS . $xmlName;
|
||||
|
||||
// Génération du XML sans output buffering
|
||||
$xml = generateXML($data);
|
||||
|
||||
// Vérification du contenu XML avant écriture
|
||||
if (empty($xml)) {
|
||||
throw new Exception("Le XML généré est vide");
|
||||
}
|
||||
|
||||
// Écriture du fichier avec vérification
|
||||
if (file_put_contents($xmlPathAndName, $xml) === false) {
|
||||
throw new Exception("Échec de l'écriture du fichier XML");
|
||||
}
|
||||
|
||||
// Vérification après écriture
|
||||
clearstatcache(true, $xmlPathAndName);
|
||||
if (!file_exists($xmlPathAndName) || filesize($xmlPathAndName) === 0) {
|
||||
throw new Exception("Le fichier XML n'a pas été créé correctement");
|
||||
}
|
||||
|
||||
// Pour debug
|
||||
error_log("Taille du XML généré : " . strlen($xml));
|
||||
error_log("Taille du fichier créé : " . filesize($xmlPathAndName));
|
||||
|
||||
$sql = 'SELECT m.rowid FROM medias m WHERE m.support_rowid = ' . $cid . ' AND support="devis_xml_sap";';
|
||||
$media = getinfos($sql);
|
||||
if ($media) {
|
||||
$sql = 'UPDATE medias SET dir0="pub/files/upload/devis/", fichier="' . $xmlName . '", type_fichier="xml", date_modif="' . date("Y-m-d H:i:s") . '", fk_user_modif=' . $fk_user . ' WHERE rowid = ' . $media[0]['rowid'] . ';';
|
||||
} else {
|
||||
$sql = 'INSERT INTO medias (support, dir0, fichier, type_fichier, support_rowid, date_creat, fk_user_creat) VALUES ("devis_xml_sap", "pub/files/upload/devis/", "' . $xmlName . '", "xml", ' . $cid . ', "' . date("Y-m-d H:i:s") . '", ' . $fk_user . ');';
|
||||
}
|
||||
qSQL($sql);
|
||||
|
||||
// Transférer via SFTP
|
||||
if (!uploadToSftp($xmlPath, $xmlName)) {
|
||||
throw new Exception("Erreur lors du transfert SFTP du fichier $xmlPath, $xmlName");
|
||||
} else {
|
||||
eLog("Fichier XML $xmlName a bien été transféré avec succès sur SFTP.");
|
||||
}
|
||||
|
||||
header("Content-type: application/xml");
|
||||
header('Content-Disposition: attachment; filename="' . $xmlName . '"');
|
||||
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
|
||||
header('Pragma: public');
|
||||
header('Expires: 0');
|
||||
echo $xml;
|
||||
exit();
|
||||
} else {
|
||||
eLog("xml_devis devis not found");
|
||||
}
|
||||
break;
|
||||
}
|
||||
exit;
|
||||
Reference in New Issue
Block a user