getOptBilanSocial(); } /** * * @return array liste des erreurs à corriger avant de pouvoir générer un BS. */ public function diagnose() { $ret = array(); try { $con = ICTIDB::getInstance(); $con->beginTransaction(); $sql = " select * from ( select case when count(oid) != 2 then 'Pas de classe(s) d''âges et/ou d''anciennetés paramétrée(s) dans Divers.' else null end as error_message from rh.t_classes join rh.t_divers on t_divers.valeur = t_classes.code WHERE 1=1 AND t_divers.code IN ('BS_CLA_AGE', 'BS_CLA_ANC') UNION select case when count(oid) = 0 then 'Aucune classe CTI_BS_QUA existante.' else null end as error_message from rh.t_classes where code = 'CTI_BS_QUA' UNION select case when count(oid) > 1 then 'Plus d''un classe CTI_BS_QUA existante.' else null end as error_message from rh.t_classes where code = 'CTI_BS_QUA' UNION select case when count(oid) = 1 and max(is_cti) != 0 then 'Classe CTI_BS_QUA ne doit pas être marquée \"CTI\".' else null end as error_message from rh.t_classes where code = 'CTI_BS_QUA' UNION select case when count(distinct t_classes.oid) = 1 AND count(distinct t_classes_sections.oid) = 0 then 'Classe CTI_BS_QUA n''a aucune section.' else null end as error_message from rh.t_classes left join rh.t_classes_sections on t_classes_sections.classe_id = t_classes.oid where 1=1 AND t_classes.code = 'CTI_BS_QUA' AND t_classes.is_cti = 0 UNION SELECT case when count(distinct t_classes.oid) = 1 then 'Classe CTI_BS_QUA définie sur une mauvaise dimension.' else null end as error_message FROM rh.t_classes join rh.t_listes_tables on t_listes_tables.oid = t_classes.table_id WHERE 1=1 AND t_classes.code = 'CTI_BS_QUA' AND is_cti = 0 AND t_listes_tables.name NOT IN ( 't_qualifications', 't_categories_socio_professionnelles', 't_services', 't_specialites', 't_statuts') ) as error_messages where error_message is not null "; foreach ($con->query($sql, PDO::FETCH_ASSOC) as $row) { $ret[] = $row; } $con->commit(); } catch (Exception $e) { } return $ret; } /** * * @return array liste des entreprises/établissements */ public function getEntities() { $ret = array(); try { $con = ICTIDB::getInstance(); $con->beginTransaction(); $sql = " SELECT * FROM ( select t_entreprises.oid AS ent_id, 0::bigint AS ets_id, t_entreprises.code_original AS code, 'Ent. '||t_entreprises.code||' - '||t_entreprises.texte AS texte from rh.t_entreprises join rh.t_etablissements on t_etablissements.entreprise_id = t_entreprises.oid join rh.p_contrats ON p_contrats.etablissement_id = t_etablissements.oid where 1=1 and t_entreprises.oid != 0 UNION select t_entreprises.oid AS ent_id, t_etablissements.oid AS ets_id, t_etablissements.code_original AS code, ' - Ets. '||t_etablissements.code||' - '||t_etablissements.texte AS texte from rh.t_entreprises join rh.t_etablissements on t_etablissements.entreprise_id = t_entreprises.oid join rh.p_contrats ON p_contrats.etablissement_id = t_etablissements.oid where 1=1 and t_entreprises.oid != 0 and t_etablissements.oid != 0) AS foo ORDER BY lpad(code, 6, '0') "; foreach ($con->query($sql, PDO::FETCH_ASSOC) as $row) { $ret[] = $row; } $con->commit(); } catch (Exception $e) { } return $ret; } public function fileGenerated($filename) { $tmpDir = __ROOT__ . '/temp/'; $outputFile = $tmpDir . $filename; return file_exists($outputFile); } public function deleteFile($filename) { $tmpDir = __ROOT__ . '/temp/'; $outputFile = $tmpDir . $filename; if (file_exists($outputFile)) { unlink($outputFile); } return true; } /** * * @param string $annee année à générer * @param array $entreprise tableau d'entreprises pour lesquelles générer le BS * @param array $etablissement tableau d'établissements pour lesquels générer le BS * @return string Description */ public function generateExcel($annee, $filename, $entrepriseId = 0, $etablissementId = 0) { $tmpDiag = $this->diagnose(); if (count($tmpDiag) > 0) { return "diagnose"; } $tmpDir = __ROOT__ . '/temp/'; // Test d'existence du dossier 'temp'. if (!file_exists($tmpDir)) { mkdir($tmpDir); } $outputFile = $tmpDir . $filename; if (file_exists($outputFile)) { unlink($outputFile); } // Récupération des données de définition du Bilan Social $fBs = __ROOT__ . '/modules/rh/php/amfphp/services/CtiRhBilanSocialService.yaml'; $data = Spyc::YAMLLoad($fBs); $conn = ICTIDB::getInstance(); $pgVersion = $conn->getAttribute(PDO::ATTR_SERVER_VERSION); $isPg9 = (intval(substr($pgVersion, 0, 1)) > 8 ? true : false); // Les classes d'âges et d'anciennetés sont paramétrées dans la table rh.t_divers. // Le programme a besoin du n° de séquence pour chacune d'entre elles. $sequenceAge = 9; $sequenceAnc = 9; $sqlDim = " SELECT t_listes_tables.name, t_classes.sequence from rh.t_classes join rh.t_listes_tables on t_listes_tables.oid = t_classes.table_id join rh.t_divers on t_divers.valeur = t_classes.code WHERE 1=1 AND t_divers.code IN ('BS_CLA_AGE', 'BS_CLA_ANC') "; $res = $conn->query($sqlDim); $tmpRes = $res->fetchAll(PDO::FETCH_ASSOC); foreach ($tmpRes as $tuple) { switch ($tuple['name']) { case 't_ages': $sequenceAge = $tuple['sequence']; break; case 't_anciennetes_annee': $sequenceAnc = $tuple['sequence']; break; } } // La classe CTI_BS_QUA peut être faite sur n'importe quelle dimension. $sqlDim = " SELECT t_listes_tables.name, t_classes.sequence from rh.t_classes join rh.t_listes_tables on t_listes_tables.oid = t_classes.table_id WHERE 1=1 AND t_classes.code = 'CTI_BS_QUA' AND is_cti = 0 LIMIT 1 "; $res = $conn->query($sqlDim); $tmpRes = $res->fetchAll(PDO::FETCH_ASSOC); $dimension = ""; $sequence = ""; switch ($tmpRes[0]['name']) { case 't_qualifications' : $dimension = "qualification"; break; case 't_categories_socio_professionnelles' : $dimension = "categorie_socio_professionnelle"; break; case 't_services' : $dimension = "service"; break; case 't_specialites' : $dimension = "specialite"; break; case 't_statuts' : $dimension = "statut"; break; default : $dimension = "statut"; break; } $sequence = $tmpRes[0]['sequence']; // Traitements SQL $sqlBase = " drop table if exists w_bs_contrat ; create temp table w_bs_contrat as select " . $dimension . "_section_texte[$sequence] AS cti_bs_qua, * from rh.v_contrats_mois_1 where 1=1 AND mois_activite_id between " . $annee . "01 and " . $annee . "12 AND est_hors_periode IS DISTINCT FROM '1' AND fictif <> '1' " . ($entrepriseId > 0 ? "AND entreprise_id = $entrepriseId" : "") . " " . ($etablissementId > 0 ? "AND etablissement_id = $etablissementId" : "") . " ; DROP TABLE IF EXISTS w_ep ; CREATE TEMP TABLE w_ep AS SELECT salarie_id AS efp_salarie_id FROM w_bs_contrat WHERE 1=1 AND present_debut_mois = 1 AND present_fin_mois = 1 GROUP BY 1 HAVING count(DISTINCT CASE WHEN 1=1 AND type_contrat_section_code[9] = 'CDI' AND type_temps_travail_section_code[9] = 'TC' THEN mois_activite_id ELSE null END) = base.cti_months_between('" . $annee . "0101'::date, '" . $annee . "1231'::date) ; DROP TABLE IF EXISTS w_bs_contrat_mois ; CREATE TEMP TABLE w_bs_contrat_mois AS SELECT mois_activite_id AS mois, " . $dimension . "_section_texte[$sequence] AS cti_bs_qua, count(DISTINCT CASE WHEN present_fin_mois = 1 THEN salarie_id ELSE null END) AS nb_sal_fin_mois FROM w_bs_contrat WHERE 1=1 GROUP BY 1,2 ; DROP TABLE IF EXISTS w_bs_arret_mois ; CREATE TEMP TABLE w_bs_arret_mois AS SELECT " . $dimension . "_section_texte[$sequence] AS cti_bs_qua, * FROM rh.v_arrets_travail_mois_1 WHERE 1=1 AND mois_activite_id between " . $annee . "01 and " . $annee . "12 " . ($entrepriseId > 0 ? "AND entreprise_id = $entrepriseId" : "") . " " . ($etablissementId > 0 ? "AND etablissement_id = $etablissementId" : "") . " ; DROP TABLE IF EXISTS w_bs_arret_mal ; CREATE TEMP TABLE w_bs_arret_mal AS SELECT cti_bs_qua, arret_travail_id, sum(nb_jours_arret) AS nb_jours_arret FROM w_bs_arret_mois WHERE 1=1 AND motif_arret_section_code[9] = 'MAL' GROUP BY 1,2 ; DROP TABLE IF EXISTS w_bs_arret_mal_duree ; CREATE TEMP TABLE w_bs_arret_mal_duree AS SELECT cti_bs_qua, arret_travail_id, nb_jours_arret, CASE WHEN nb_jours_arret BETWEEN 1 AND 3 THEN 'T01|1 à 3 jours' WHEN nb_jours_arret BETWEEN 4 AND 10 THEN 'T02|4 à 10 jours' WHEN nb_jours_arret BETWEEN 10 AND 15 THEN 'T03|10 à 15 jours' WHEN nb_jours_arret BETWEEN 16 AND 30 THEN 'T04|16 à 30 jours' WHEN nb_jours_arret BETWEEN 31 AND 60 THEN 'T05|1 à 2 mois' WHEN nb_jours_arret BETWEEN 61 AND 90 THEN 'T06|2 à 3 mois' WHEN nb_jours_arret BETWEEN 91 AND 120 THEN 'T07|3 à 4 mois' WHEN nb_jours_arret BETWEEN 121 AND 150 THEN 'T08|4 à 5 mois' WHEN nb_jours_arret BETWEEN 151 AND 180 THEN 'T09|5 à 6 mois' WHEN nb_jours_arret BETWEEN 181 AND 212 THEN 'T10|6 à 7 mois' WHEN nb_jours_arret BETWEEN 213 AND 244 THEN 'T11|7 à 8 mois' WHEN nb_jours_arret BETWEEN 245 AND 274 THEN 'T12|8 à 9 mois' WHEN nb_jours_arret BETWEEN 275 AND 304 THEN 'T13|9 à 10 mois' WHEN nb_jours_arret BETWEEN 305 AND 334 THEN 'T14|10 à 11 mois' WHEN nb_jours_arret BETWEEN 335 AND 365 THEN 'T15|11 à 12 mois' ELSE 'T16|+ d''un an' END AS tranche_duree FROM w_bs_arret_mal ; drop table if exists w_bs_paie ; create temp table w_bs_paie as select " . $dimension . "_section_texte[$sequence] AS cti_bs_qua, mois_activite_id, salarie_id, rubrique_id, montant_masse_salariale, montant_net_a_payer_salarie from rh.v_historique_paie_1 where 1=1 AND mois_activite_id between " . $annee . "01 and " . $annee . "12 " . ($entrepriseId > 0 ? "AND entreprise_id = $entrepriseId" : "") . " " . ($etablissementId > 0 ? "AND etablissement_id = $etablissementId" : "") . " ; DROP TABLE IF EXISTS w_bs_paie_mois ; CREATE TEMP TABLE w_bs_paie_mois AS SELECT mois, cti_bs_qua, sum(nb_cnt_salarie_id) AS nb_cnt_salarie_id, sum(nb_cnt_sal_fin_mois) AS nb_cnt_sal_fin_mois, sum(montant_masse_salariale) AS montant_masse_salariale FROM ( SELECT mois_activite_id AS mois, cti_bs_qua, count(DISTINCT salarie_id) AS nb_cnt_salarie_id, count(DISTINCT CASE WHEN present_fin_mois = 1 THEN salarie_id ELSE NULL END) AS nb_cnt_sal_fin_mois, 0 AS montant_masse_salariale FROM w_bs_contrat GROUP BY 1,2 UNION ALL SELECT mois_activite_id, cti_bs_qua, 0, 0, sum(montant_masse_salariale) FROM w_bs_paie GROUP BY 1,2 ) AS subq GROUP BY 1,2 ; "; if ($isPg9) { $sqlBase .= " -- Spécial paie DROP TABLE IF EXISTS w_bs_paie_special ; CREATE TEMP TABLE w_bs_paie_special AS SELECT salarie_id, foo.cti_bs_qua, 0::BIGINT AS i, 0::BIGINT AS j, sum(montant_masse_salariale) AS montant_masse_salariale, 0::NUMERIC AS s10m, -- rémunérations représentant 10% des salariés avec les rémunérations les moins élevées 0::NUMERIC AS s10p, -- rémunérations représentant 10% des salariés avec les rémunérations les plus élevées 0::NUMERIC AS m10p -- montant des 10 rémunérations les + élevées FROM w_bs_paie JOIN w_ep ON efp_salarie_id = salarie_id JOIN ( SELECT cti_bs_qua FROM w_bs_paie GROUP BY 1 UNION ALL SELECT 'Total' ) AS foo ON 1 = 1 WHERE 1!=1 OR foo.cti_bs_qua = 'Total' OR foo.cti_bs_qua = w_bs_paie.cti_bs_qua GROUP BY 1,2,3,4,6,7 ; -- Remplir le rang par cti_bs_qua UPDATE w_bs_paie_special SET i = ir, j=jr FROM ( SELECT rank() OVER (PARTITION BY cti_bs_qua ORDER BY montant_masse_salariale asc) AS ir, rank() OVER (PARTITION BY cti_bs_qua ORDER BY montant_masse_salariale desc) AS jr, * FROM w_bs_paie_special ) AS foo WHERE 1 = 1 AND w_bs_paie_special.salarie_id = foo.salarie_id AND w_bs_paie_special.cti_bs_qua = foo.cti_bs_qua ; UPDATE w_bs_paie_special SET s10m = foo1.s10m, s10p = foo1.s10p, m10p = foo1.m10p FROM ( SELECT salarie_id, i, w_bs_paie_special.cti_bs_qua, foo.cti_bs_qua AS ttt, CASE WHEN ( i::NUMERIC / ( SELECT count(*)::NUMERIC FROM w_bs_paie_special WHERE cti_bs_qua = foo.cti_bs_qua ) * 100::NUMERIC ) >= 90 THEN montant_masse_salariale ELSE 0 END AS s10p, CASE WHEN ( ( ( SELECT count(*)::NUMERIC FROM w_bs_paie_special WHERE cti_bs_qua = foo.cti_bs_qua ) - i::NUMERIC + 1 ) / ( SELECT count(*)::NUMERIC FROM w_bs_paie_special WHERE cti_bs_qua = foo.cti_bs_qua ) * 100::NUMERIC ) >= 90 THEN montant_masse_salariale ELSE 0 END AS s10m, case when j <= 10 then montant_masse_salariale else 0 end as m10p FROM w_bs_paie_special JOIN ( SELECT cti_bs_qua FROM w_bs_paie GROUP BY 1 UNION ALL SELECT 'Total' ) AS foo ON w_bs_paie_special.cti_bs_qua = foo.cti_bs_qua GROUP BY 1,2,3,4,5,6,7 ORDER BY 2,4,3 ) AS foo1 WHERE 1 = 1 AND w_bs_paie_special.salarie_id = foo1.salarie_id AND w_bs_paie_special.cti_bs_qua = foo1.cti_bs_qua ; "; } $remplacements = array( '@annee' => $annee, '@sequenceAge' => $sequenceAge, '@sequenceAnc' => $sequenceAnc ); $wBsContratSQL = array(); // requetes sur w_bs_contrat $wBsContratMoisSQL = array(); // requetes sur w_bs_contrat_mois $wBsArretMoisSQL = array(); // requetes sur w_bs_arret_mois $wBsArretMalDureeSQL = array(); // requetes sur w_bs_arret_mal_duree $wBsPaieSQL = array(); // requetes sur w_bs_paie $wBsPaieMoisSQL = array(); // requetes sur w_bs_paie_mois $wBsPaieSpecialSQL = array(); // requetes sur w_bs_paie_special $currentTempTable = ""; // Table temporaire associée à l'indicateur // Parcours de tous les indicateurs pour constituer la requête SQL foreach ($data['bilanSocial2013'] as $niveau1) { if (key_exists('e', $niveau1)) { foreach ($niveau1['e'] as $niveau2) { if (key_exists('e', $niveau2)) { foreach ($niveau2['e'] as $indicateur) { $tmpIndicatorName = $niveau1['i'] . '.' . $niveau2['i'] . '.' . $indicateur['i']; $tmpNull = "null" . ' AS "' . $tmpIndicatorName . '"'; // Recherche de la table de travail pour l'indicateur. if (key_exists('o', $indicateur)) { $currentTempTable = $indicateur['o']; } else if (key_exists('o', $niveau2)) { $currentTempTable = $niveau2['o']; } else if (key_exists('o', $niveau1)) { $currentTempTable = $niveau1['o']; } else { // ERREUR : pas de table définie... } $wBsContratSQL[] = $tmpNull; $wBsContratMoisSQL[] = $tmpNull; $wBsArretMoisSQL[] = $tmpNull; $wBsArretMalDureeSQL[] = $tmpNull; $wBsPaieSQL[] = $tmpNull; $wBsPaieMoisSQL[] = $tmpNull; $wBsPaieSpecialSQL[] = $tmpNull; if (key_exists('s', $indicateur)) { $tmp = strtr($indicateur['s'], $remplacements) . ' AS "' . $tmpIndicatorName . '"'; switch ($currentTempTable) { case 'w_bs_contrat' : $wBsContratSQL[] = $tmp; break; case 'w_bs_contrat_mois': $wBsContratMoisSQL[] = $tmp; break; case 'w_bs_arret_mois': $wBsArretMoisSQL[] = $tmp; break; case 'w_bs_arret_mal_duree': $wBsArretMalDureeSQL[] = $tmp; break; case 'w_bs_paie': $wBsPaieSQL[] = $tmp; break; case 'w_bs_paie_mois': $wBsPaieMoisSQL[] = $tmp; break; case 'w_bs_paie_special': $wBsPaieSpecialSQL[] = $tmp; break; } } // Dans le cas d'indicateurs enfants. if (key_exists('e', $indicateur)) { foreach ($indicateur['e'] as $indicateurEnfant) { if (key_exists('s', $indicateurEnfant)) { $tmpIndicatorName = $niveau1['i'] . '.' . $niveau2['i'] . '.' . $indicateur['i'].'.'.$indicateurEnfant['i']; $tmpNull = "null" . ' AS "' . $tmpIndicatorName . '"'; // La table de travail est actuellement celle de l'indicateur parent par défaut. $tmp = strtr($indicateurEnfant['s'], $remplacements) . ' AS "' . $tmpIndicatorName . '"'; $wBsContratSQL[] = $tmpNull; $wBsContratMoisSQL[] = $tmpNull; $wBsArretMoisSQL[] = $tmpNull; $wBsArretMalDureeSQL[] = $tmpNull; $wBsPaieSQL[] = $tmpNull; $wBsPaieMoisSQL[] = $tmpNull; $wBsPaieSpecialSQL[] = $tmpNull; switch ($currentTempTable) { case 'w_bs_contrat' : $wBsContratSQL[] = $tmp; break; case 'w_bs_contrat_mois': $wBsContratMoisSQL[] = $tmp; break; case 'w_bs_arret_mois': $wBsArretMoisSQL[] = $tmp; break; case 'w_bs_arret_mal_duree': $wBsArretMalDureeSQL[] = $tmp; break; case 'w_bs_paie': $wBsPaieSQL[] = $tmp; break; case 'w_bs_paie_mois': $wBsPaieMoisSQL[] = $tmp; break; case 'w_bs_paie_special': $wBsPaieSpecialSQL[] = $tmp; break; } } } } } } } } } // Exécution de la requête $sqlCmd = $sqlBase . PHP_EOL; // Contrats $sqlCmd .= " SELECT 1 AS level, cti_bs_qua,"; $sqlCmd .= implode(',', $wBsContratSQL); $sqlCmd .= PHP_EOL . "from w_bs_contrat left join w_ep on w_ep.efp_salarie_id = w_bs_contrat.salarie_id where 1=1 group by 1,2 UNION ALL select 0, 'Total'::text, "; $sqlCmd .= implode(',', $wBsContratSQL); $sqlCmd .= PHP_EOL . "from w_bs_contrat left join w_ep on w_ep.efp_salarie_id = w_bs_contrat.salarie_id where 1=1 group by 1,2 ORDER BY 1 DESC, 2 "; // Contrats mois $monthlySqlCmd = " SELECT 1 AS level, cti_bs_qua,"; $monthlySqlCmd .= implode(',', $wBsContratMoisSQL); $monthlySqlCmd .= PHP_EOL . "from w_bs_contrat_mois where 1=1 group by 1,2 UNION ALL select 0, 'Total'::text, "; $monthlySqlCmd .= implode(',', $wBsContratMoisSQL); $monthlySqlCmd .= PHP_EOL . "from w_bs_contrat_mois where 1=1 group by 1,2 ORDER BY 1 DESC, 2 "; // Arrets $arretSqlCmd = " SELECT 1 AS level, cti_bs_qua,"; $arretSqlCmd .= implode(',', $wBsArretMoisSQL); $arretSqlCmd .= PHP_EOL . "from w_bs_arret_mois where 1=1 group by 1,2 UNION ALL select 0, 'Total'::text, "; $arretSqlCmd .= implode(',', $wBsArretMoisSQL); $arretSqlCmd .= PHP_EOL . "from w_bs_arret_mois where 1=1 group by 1,2 ORDER BY 1 DESC, 2 "; // Arrets Maladie Durée $arretMalDureeSqlCmd = " SELECT 1 AS level, cti_bs_qua,"; $arretMalDureeSqlCmd .= implode(',', $wBsArretMalDureeSQL); $arretMalDureeSqlCmd .= PHP_EOL . "from w_bs_arret_mal_duree where 1=1 group by 1,2 UNION ALL select 0, 'Total'::text, "; $arretMalDureeSqlCmd .= implode(',', $wBsArretMalDureeSQL); $arretMalDureeSqlCmd .= PHP_EOL . "from w_bs_arret_mal_duree where 1=1 group by 1,2 ORDER BY 1 DESC, 2 "; // Paies $paieSqlCmd = " SELECT 1 AS level, cti_bs_qua,"; $paieSqlCmd .= implode(',', $wBsPaieSQL); $paieSqlCmd .= PHP_EOL . "from w_bs_paie left join w_ep on w_ep.efp_salarie_id = w_bs_paie.salarie_id where 1=1 group by 1,2 UNION ALL select 0, 'Total'::text, "; $paieSqlCmd .= implode(',', $wBsPaieSQL); $paieSqlCmd .= PHP_EOL . "from w_bs_paie left join w_ep on w_ep.efp_salarie_id = w_bs_paie.salarie_id where 1=1 group by 1,2 ORDER BY 1 DESC, 2 "; // Paies Mois $paieMoisSqlCmd = " SELECT 1 AS level, cti_bs_qua,"; $paieMoisSqlCmd .= implode(',', $wBsPaieMoisSQL); $paieMoisSqlCmd .= PHP_EOL . "from w_bs_paie_mois where 1=1 group by 1,2 UNION ALL select 0, 'Total'::text, "; $paieMoisSqlCmd .= implode(',', $wBsPaieMoisSQL); $paieMoisSqlCmd .= PHP_EOL . "from w_bs_paie_mois where 1=1 group by 1,2 ORDER BY 1 DESC, 2 "; if ($isPg9) { // Paies Special $paieSpecialSqlCmd = " SELECT 1 AS level, cti_bs_qua,"; $paieSpecialSqlCmd .= implode(',', $wBsPaieSpecialSQL); $paieSpecialSqlCmd .= PHP_EOL . "from w_bs_paie_special where 1=1 group by 1,2 UNION ALL select 0, 'Total'::text, "; $paieSpecialSqlCmd .= implode(',', $wBsPaieSpecialSQL); $paieSpecialSqlCmd .= PHP_EOL . "from w_bs_paie_special where 1=1 group by 1,2 ORDER BY 1 DESC, 2 "; } // Traitement des résultat Contrat $res = $conn->query($sqlCmd); $tmpRes = $res->fetchAll(PDO::FETCH_ASSOC); $nbDataCol = count($tmpRes); $iDataRes = array(); foreach ($tmpRes as $value) { foreach ($value as $key1 => $value1) { if ($key1 != 'level' || $key1 != 'cti_bs_qua') { $iDataRes[$key1][$value['cti_bs_qua']] = $value1; } } } // Traitement des résultat Contrats mois $res = $conn->query($monthlySqlCmd); $tmpRes = $res->fetchAll(PDO::FETCH_ASSOC); foreach ($tmpRes as $value) { foreach ($value as $key1 => $value1) { if ($key1 != 'level' || $key1 != 'cti_bs_qua') { if (!isset($iDataRes[$key1][$value['cti_bs_qua']])) { $iDataRes[$key1][$value['cti_bs_qua']] = $value1; } } } } // Traitement des résultat Arrets. $res = $conn->query($arretSqlCmd); $tmpRes = $res->fetchAll(PDO::FETCH_ASSOC); foreach ($tmpRes as $value) { foreach ($value as $key1 => $value1) { if ($key1 != 'level' || $key1 != 'cti_bs_qua') { if (!isset($iDataRes[$key1][$value['cti_bs_qua']])) { $iDataRes[$key1][$value['cti_bs_qua']] = $value1; } } } } // Traitement des résultat Arrets maladie durée. $res = $conn->query($arretMalDureeSqlCmd); $tmpRes = $res->fetchAll(PDO::FETCH_ASSOC); foreach ($tmpRes as $value) { foreach ($value as $key1 => $value1) { if ($key1 != 'level' || $key1 != 'cti_bs_qua') { if (!isset($iDataRes[$key1][$value['cti_bs_qua']])) { $iDataRes[$key1][$value['cti_bs_qua']] = $value1; } } } } // Traitement des résultat Paies. $res = $conn->query($paieSqlCmd); $tmpRes = $res->fetchAll(PDO::FETCH_ASSOC); foreach ($tmpRes as $value) { foreach ($value as $key1 => $value1) { if ($key1 != 'level' || $key1 != 'cti_bs_qua') { if (!isset($iDataRes[$key1][$value['cti_bs_qua']])) { $iDataRes[$key1][$value['cti_bs_qua']] = $value1; } } } } // Traitement des résultat Paies Mois. $res = $conn->query($paieMoisSqlCmd); $tmpRes = $res->fetchAll(PDO::FETCH_ASSOC); foreach ($tmpRes as $value) { foreach ($value as $key1 => $value1) { if ($key1 != 'level' || $key1 != 'cti_bs_qua') { if (!isset($iDataRes[$key1][$value['cti_bs_qua']])) { $iDataRes[$key1][$value['cti_bs_qua']] = $value1; } } } } // Traitement des résultat Paies Spéciales. if ($isPg9) { $res = $conn->query($paieSpecialSqlCmd); $tmpRes = $res->fetchAll(PDO::FETCH_ASSOC); foreach ($tmpRes as $value) { foreach ($value as $key1 => $value1) { if ($key1 != 'level' || $key1 != 'cti_bs_qua') { if (!isset($iDataRes[$key1][$value['cti_bs_qua']])) { $iDataRes[$key1][$value['cti_bs_qua']] = $value1; } } } } } // Génération du fichier Excel $objPHPExcel = new PHPExcel(); $objPHPExcel->getProperties()->setCreator("CTI Santé"); $objPHPExcel->getProperties()->setLastModifiedBy("CTI Santé"); $objPHPExcel->getProperties()->setTitle("Bilan social $annee"); $objPHPExcel->getProperties()->setSubject("Bilan social $annee"); $objPHPExcel->getProperties()->setDescription("Bilan social $annee - CTI Santé"); $objPHPExcel->removeSheetByIndex(); // Suppression feuille par défaut "Worksheet" $sheetIndex = 0; $gras = array( 'font' => array( 'size' => 12, 'bold' => true, 'color' => array( 'rgb' => 'FFFFFF' ) ) ); $gras2 = array( 'font' => array( 'bold' => true ) ); $fill = array( 'type' => PHPExcel_Style_Fill::FILL_SOLID, 'color' => array('rgb' => '012b43') ) ; $dataOddFill = array( 'type' => PHPExcel_Style_Fill::FILL_SOLID, 'color' => array('rgb' => 'EEEEEE') ) ; $totalOddFill = array( 'type' => PHPExcel_Style_Fill::FILL_SOLID, 'color' => array('rgb' => 'CCCCCC') ) ; $totalEvenFill = array( 'type' => PHPExcel_Style_Fill::FILL_SOLID, 'color' => array('rgb' => 'EEEEEE') ) ; $NRFont = array( 'font' => array( 'color' => array( 'rgb' => 'FF552A' ) ) ); $alignmentVC = array( 'vertical' => PHPExcel_Style_Alignment::VERTICAL_CENTER ); $alignmentHCVC = array( 'horizontal' => PHPExcel_Style_Alignment::HORIZONTAL_CENTER, 'vertical' => PHPExcel_Style_Alignment::VERTICAL_CENTER ); $alignmentHCW = array( 'horizontal' => PHPExcel_Style_Alignment::HORIZONTAL_CENTER, 'wrap' => true ); $alignmentW = array('wrap' => true); $alignmentVT = array('vertical' => PHPExcel_Style_Alignment::VERTICAL_TOP); foreach ($data['bilanSocial2013'] as $niveau1) { //echo PHP_EOL . $niveau1['t']; $sheetName = utf8_encode($niveau1['i'] . '. ' . $niveau1['t']); $objPHPExcel->createSheet($sheetIndex); $objPHPExcel->setActiveSheetIndex($sheetIndex); $sheet = $objPHPExcel->getActiveSheet(); $sheet->getPageSetup()->setPaperSize(PHPExcel_Worksheet_PageSetup::PAPERSIZE_A4); $sheet->getPageSetup()->setOrientation(PHPExcel_Worksheet_PageSetup::ORIENTATION_LANDSCAPE); //$sheet->getPageSetup()->setScale(20); $sheet->getPageSetup()->setFitToPage(true); $sheet->getPageSetup()->setFitToWidth(1); $sheet->getPageSetup()->setFitToHeight(0); $sheet->getPageSetup()->setHorizontalCentered(true); $sheet->getPageSetup()->setVerticalCentered(true); //$sheet->getHeaderFooter()->setOddHeader('&A'); $sheet->getHeaderFooter()->setOddHeader("Bilan Social $annee " . html_entity_decode("• ", ENT_COMPAT | ENT_HTML401, 'UTF-8') . ' ' . utf8_encode($niveau1['i'] . '. ' . $niveau1['xt'])); $sheet->getHeaderFooter()->setOddFooter('Page &P de &N'); //$sheet->getHeaderFooter()->setEvenFooter('Page &P de &N'); $sheet->setTitle($sheetName); $sheet->getColumnDimensionByColumn(0)->setWidth(5); $sheet->getColumnDimensionByColumn(1)->setWidth(50); for ($i = 2; $i <= (count($iDataRes["cti_bs_qua"]) + 1); $i++) { $sheet->getColumnDimensionByColumn($i)->setWidth(15); } $c = 1; $r = 1; if (key_exists('e', $niveau1)) { foreach ($niveau1['e'] as $niveau2) { $sheet->setCellValueExplicit($this->cvt(1, $r), utf8_encode($niveau1['i'] . '.' . $niveau2['i']), PHPExcel_Cell_DataType::TYPE_STRING); $sheet->setCellValueExplicit($this->cvt(2, $r), utf8_encode($niveau2['t']), PHPExcel_Cell_DataType::TYPE_STRING); $sheet->getStyle($this->cvt(1, $r, $nbDataCol + 2, $r))->getAlignment()->applyFromArray($alignmentVC); $sheet->getStyle($this->cvt(3, $r, $nbDataCol + 2, $r))->getAlignment()->applyFromArray($alignmentHCW); $sheet->getStyle($this->cvt(1, $r, $nbDataCol + 2, $r))->applyFromArray($gras); $sheet->getStyle($this->cvt(1, $r, $nbDataCol + 2, $r))->getFill()->applyFromArray($fill); if (key_exists('c', $niveau2)) { $sheet->getComment($this->cvt(2, $r))->getText()->createTextRun(utf8_encode($niveau2['c'])); } // Ecriture de l'entête de tableau $i = 2; foreach ($iDataRes["cti_bs_qua"] as $value) { $sheet->setCellValueExplicitByColumnAndRow($i, $r, utf8_encode($value), PHPExcel_Cell_DataType::TYPE_STRING); $i++; } $sheet->getRowDimension($r)->setRowHeight(30); $r++; if (key_exists('e', $niveau2)) { foreach ($niveau2['e'] as $indicateur) { $indicateurNom = $niveau1['i'] . '.' . $niveau2['i'] . '.' . $indicateur['i']; $sheet->setCellValueExplicitByColumnAndRow(0, $r, utf8_encode($indicateurNom), PHPExcel_Cell_DataType::TYPE_STRING); $sheet->setCellValueExplicitByColumnAndRow(1, $r, utf8_encode($indicateur['t']), PHPExcel_Cell_DataType::TYPE_STRING); if ($this->is_odd($r)) { $sheet->getStyle($this->cvt(1, $r, $nbDataCol + 1, $r))->getFill()->applyFromArray($dataOddFill); $sheet->getStyleByColumnAndRow($nbDataCol + 1, $r)->getFill()->applyFromArray($totalOddFill); $sheet->getStyle($this->cvt(1, $r, 2, $r))->getFill()->applyFromArray($totalOddFill); } else { $sheet->getStyleByColumnAndRow($nbDataCol + 1, $r)->getFill()->applyFromArray($totalEvenFill); $sheet->getStyle($this->cvt(1, $r, 2, $r))->getFill()->applyFromArray($totalEvenFill); } $sheet->getStyleByColumnAndRow($nbDataCol + 1, $r)->applyFromArray($gras2); if (key_exists('c', $indicateur)) { $sheet->getCommentByColumnAndRow(1, $r)->getText()->createTextRun(utf8_encode($indicateur['c'])); } // Rechercher le format du nombre à appliquer. if (key_exists('f', $indicateur)) { $format = html_entity_decode(utf8_encode($indicateur['f']), ENT_COMPAT | ENT_HTML401, 'UTF-8'); } else if (key_exists('f', $niveau2)) { $format = html_entity_decode(utf8_encode($niveau2['f']), ENT_COMPAT | ENT_HTML401, 'UTF-8'); } else if (key_exists('f', $niveau1)) { $format = html_entity_decode(utf8_encode($niveau1['f']), ENT_COMPAT | ENT_HTML401, 'UTF-8'); } else { // ERREUR : pas de format défini... } // Détecter si plusieurs sous niveau $subLevelType = 0; // Traitement des valeurs encapsulées dans {} if (substr($iDataRes[$indicateurNom]['Total'], 0, 2) == '{{') { $subLevelType = 1; } // Traitements des enfants non numérotés if (key_exists('e', $indicateur)) { $subLevelType = 2; } // Si indicateur standard (sans sous-niveau) ou // si indicateur avec enfants (définis à la main avec noeud de type e:) et avec une définition SQL, // alors on inscrit le résultat, sinon rien. if ($subLevelType === 0 || ($subLevelType === 2 && key_exists('s', $indicateur))) { $sheet->getStyleByColumnAndRow(0, $r)->getAlignment()->applyFromArray($alignmentVT); $sheet->getStyleByColumnAndRow(1, $r)->getAlignment()->applyFromArray($alignmentW); $rowNR = true; $i = 2; foreach ($iDataRes[$indicateurNom] as $header => $value) { $sheet->setCellValueExplicitByColumnAndRow($i, $r, utf8_encode($value), PHPExcel_Cell_DataType::TYPE_NUMERIC); if (isset($value)) { $rowNR = false; } $i++; } $sheet->getStyle($this->cvt(3, $r, $nbDataCol + 2, $r))->getAlignment()->applyFromArray($alignmentHCVC); if ($rowNR) { $sheet->getStyle($this->cvt(3, $r, $nbDataCol + 2, $r))->applyFromArray($NRFont); } else { $sheet->getStyle($this->cvt(3, $r, $nbDataCol + 2, $r))->getNumberFormat()->setFormatCode($format); } } // Traitement des sous-niveaux. switch ($subLevelType) { case 1: $tmpDba = array(); foreach ($iDataRes[$indicateurNom] as $header => $value2) { $tmpVal = preg_split("/({{|},{|}})/", $value2, -1, PREG_SPLIT_NO_EMPTY); foreach ($tmpVal as $value4) { $tmpSubLevelValue = explode(',', $value4); $tmpDba[$tmpSubLevelValue[0]][$header] = $tmpSubLevelValue[1]; } } if (key_exists('sort', $indicateur)) { if ($indicateur['sort'] == "asc") { uksort($tmpDba, array($this, "classeSectionCompareAsc")); } else { uksort($tmpDba, array($this, "classeSectionCompareDesc")); } } foreach ($tmpDba as $cHeader => $value3) { $tmp = explode('|', $cHeader); $header = trim($tmp[1], "\""); $r++; $sheet->setCellValueExplicitByColumnAndRow(1, $r, html_entity_decode("• ", ENT_COMPAT | ENT_HTML401, 'UTF-8') . utf8_encode($header), PHPExcel_Cell_DataType::TYPE_STRING); $sheet->getStyleByColumnAndRow(0, $r)->getAlignment()->applyFromArray($alignmentVT); $sheet->getStyleByColumnAndRow(1, $r)->getAlignment()->applyFromArray($alignmentW); if ($this->is_odd($r)) { $sheet->getStyle($this->cvt(1, $r, $nbDataCol + 1, $r))->getFill()->applyFromArray($dataOddFill); $sheet->getStyleByColumnAndRow($nbDataCol + 1, $r)->getFill()->applyFromArray($totalOddFill); $sheet->getStyle($this->cvt(1, $r, 2, $r))->getFill()->applyFromArray($totalOddFill); } else { $sheet->getStyleByColumnAndRow($nbDataCol + 1, $r)->getFill()->applyFromArray($totalEvenFill); $sheet->getStyle($this->cvt(1, $r, 2, $r))->getFill()->applyFromArray($totalEvenFill); } $sheet->getStyleByColumnAndRow($nbDataCol + 1, $r)->applyFromArray($gras2); $rowNR = true; $i = 2; foreach ($iDataRes[$indicateurNom] as $header => $value) { $sheet->setCellValueExplicitByColumnAndRow($i, $r, utf8_encode($value3[$header]), PHPExcel_Cell_DataType::TYPE_NUMERIC); if (isset($value3[$header])) { $rowNR = false; } $i++; } $sheet->getStyle($this->cvt(3, $r, $nbDataCol + 2, $r))->getAlignment()->applyFromArray($alignmentHCVC); if ($rowNR) { $sheet->getStyle($this->cvt(3, $r, $nbDataCol + 2, $r))->applyFromArray($NRFont); } else { $sheet->getStyle($this->cvt(3, $r, $nbDataCol + 2, $r))->getNumberFormat()->setFormatCode($format); } } break; case 2: foreach ($indicateur['e'] as $subChild) { $r++; $sheet->setCellValueExplicitByColumnAndRow(1, $r, html_entity_decode("• ", ENT_COMPAT | ENT_HTML401, 'UTF-8') . utf8_encode($subChild['t']), PHPExcel_Cell_DataType::TYPE_STRING); $sheet->getStyleByColumnAndRow(0, $r)->getAlignment()->applyFromArray($alignmentVT); $sheet->getStyleByColumnAndRow(1, $r)->getAlignment()->applyFromArray($alignmentW); if ($this->is_odd($r)) { $sheet->getStyle($this->cvt(1, $r, $nbDataCol + 1, $r))->getFill()->applyFromArray($dataOddFill); $sheet->getStyleByColumnAndRow($nbDataCol + 1, $r)->getFill()->applyFromArray($totalOddFill); $sheet->getStyle($this->cvt(1, $r, 2, $r))->getFill()->applyFromArray($totalOddFill); } else { $sheet->getStyleByColumnAndRow($nbDataCol + 1, $r)->getFill()->applyFromArray($totalEvenFill); $sheet->getStyle($this->cvt(1, $r, 2, $r))->getFill()->applyFromArray($totalEvenFill); } $sheet->getStyleByColumnAndRow($nbDataCol + 1, $r)->applyFromArray($gras2); // clef "c" : commentaire de cellule. if (key_exists('c', $subChild)) { $sheet->getCommentByColumnAndRow(1, $r)->getText()->createTextRun(utf8_encode($subChild['c'])); } // clef "v" : visibilité de ligne. if (key_exists('v', $subChild)) { $sheet->getRowDimension($r)->setVisible($subChild['v'] === 'true'); } $rowNR = true; $i = 2; foreach ($iDataRes[$indicateurNom.'.'.$subChild['i']] as $header => $value) { $sheet->setCellValueExplicitByColumnAndRow($i, $r, utf8_encode($value), PHPExcel_Cell_DataType::TYPE_NUMERIC); if (isset($value)) { $rowNR = false; } $i++; } $subChildFormat = $format; if (key_exists('f', $subChild)) { $subChildFormat = html_entity_decode(utf8_encode($subChild['f']), ENT_COMPAT | ENT_HTML401, 'UTF-8'); } $sheet->getStyle($this->cvt(3, $r, $nbDataCol + 2, $r))->getAlignment()->applyFromArray($alignmentHCVC); if ($rowNR) { $sheet->getStyle($this->cvt(3, $r, $nbDataCol + 2, $r))->applyFromArray($NRFont); } else { $sheet->getStyle($this->cvt(3, $r, $nbDataCol + 2, $r))->getNumberFormat()->setFormatCode($subChildFormat); } } break; default: // Pas de comportement par défaut. break; } $r++; } } } } $sheetIndex++; } $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); //$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel); $objWriter->save($outputFile); return $outputFile; } private function cvt($c, $r, $c1 = null, $r1 = null) { if ($c1 == null) { return PHPExcel_Calculation_LookupRef::CELL_ADDRESS($r, $c, 4); } else { return PHPExcel_Calculation_LookupRef::CELL_ADDRESS($r, $c, 4) . ':' . PHPExcel_Calculation_LookupRef::CELL_ADDRESS($r1, $c1, 4); } } private function is_odd($n) { return (boolean) ($n % 2); } public function classeSectionCompareAsc($s1, $s2) { return $this->classeSectionCompare($s1, $s2, "asc"); } public function classeSectionCompareDesc($s1, $s2) { return $this->classeSectionCompare($s1, $s2, "desc"); } private function classeSectionCompare($s1, $s2, $dir = "asc") { $tmp1 = explode('|', $s1); $a = trim($tmp1[0], "\""); $tmp2 = explode('|', $s2); $b = trim($tmp2[0], "\""); if ($a == $b) { $r = 0; } else { if ($dir == "asc") { $r = ($a > $b) ? 1 : -1; } else { $r = ($b > $a) ? 1 : -1; } } return $r; } }