<?php
|
|
|
|
class ControleExpertManager {
|
|
|
|
|
|
//********************************************************************************************
|
|
//
|
|
// VARIABLES
|
|
//
|
|
//********************************************************************************************/
|
|
|
|
private $etat_cible = array(
|
|
|
|
0 => array( "name" => 'Tous',
|
|
"where" => ''),
|
|
|
|
1 => array( "name" => 'Présents',
|
|
"where" => 'AND ((code_sorti IS DISTINCT FROM 1) OR (date_sortie >= date(now())))'),
|
|
|
|
2 => array( "name" => 'Non facturés',
|
|
"where" => "AND date_facture = '2099-12-31'::date")
|
|
);
|
|
|
|
const JUSTIF_SEPARATOR = ":";
|
|
|
|
// Nom de la base de données iCTI
|
|
const DATABASE_NAME = 'iCTI';
|
|
// Classe de la connexion à la base iCTI
|
|
const DATABASE_CLASS = 'Database';
|
|
|
|
// Tables sur lequelles on peut faire tourner des règles
|
|
private $tables = array(
|
|
// séjours
|
|
0 => array( "name" => 'v_sejours_1',
|
|
"fictive" => false,
|
|
"from" => 'activite.v_sejours_1',
|
|
"fields" => array(),
|
|
"defaults" => array('v_sejours_1.sejour_id', 'v_sejours_1.no_sejour', 'v_sejours_1.date_sortie')),
|
|
// mouvements
|
|
1 => array( "name" => 'v_mouvements_sejour_r_1',
|
|
"fictive" => false,
|
|
"from" => 'activite.v_mouvements_sejour_r_1',
|
|
"fields" => array(),
|
|
"defaults" => array('v_mouvements_sejour_r_1.sejour_id', 'v_mouvements_sejour_r_1.no_sejour', 'v_mouvements_sejour_r_1.date_sortie')),
|
|
// factures
|
|
2 => array( "name" => 'v_factures_reference_r_2',
|
|
"fictive" => false,
|
|
"from" => 'activite.v_factures_reference_r_2',
|
|
"fields" => array(),
|
|
"defaults" => array('v_factures_reference_r_2.sejour_id', 'v_factures_reference_r_2.no_sejour', 'v_factures_reference_r_2.date_sortie')),
|
|
// lignes factures honoraires
|
|
3 => array( "name" => 'v_factures_lignes_h_r_1',
|
|
"fictive" => false,
|
|
"from" => 'activite.v_factures_lignes_h_r_1',
|
|
"fields" => array(),
|
|
"defaults" => array('v_factures_lignes_h_r_1.sejour_id', 'v_factures_lignes_h_r_1.no_sejour', 'v_factures_lignes_h_r_1.date_sortie')),
|
|
// sql brut
|
|
99 => array( "name" => '',
|
|
"fictive" => true,
|
|
"from" => '',
|
|
"fields" => array(),
|
|
"defaults" => array('v_sejours_1.sejour_id', 'v_sejours_1.no_sejour', 'v_sejours_1.date_sortie'))
|
|
);
|
|
|
|
// Tableau des contrôles
|
|
private $controls;
|
|
|
|
// Connexion à la base de données
|
|
private $database;
|
|
|
|
// Indique le que le manager de controle expert est prêt à fonctionner (Connction DB OK et
|
|
// initialisations réalisées
|
|
private $ready;
|
|
|
|
// Message d'erreur en cas d'erreur justement
|
|
private $error_msg;
|
|
|
|
// Indique si le module expert est activé
|
|
private $expert_active;
|
|
|
|
// Date à partir de laquelle les séjours sont contrôlables
|
|
private $expert_date_debut;
|
|
|
|
// Nombre de résultats positifs aux contrôles expert
|
|
private $nb_results;
|
|
|
|
// Message de retour
|
|
private $msg;
|
|
|
|
// Nombre de contrôles chargés
|
|
private $nb_controls;
|
|
|
|
// Emplacement absolu du fichier de traduction des champs des justificatifs
|
|
private $dictionary;
|
|
|
|
// Tableau des valeurs du dictionnaire de traduction
|
|
private $dict_array;
|
|
|
|
// Module qui exécute le contrôle expert (activite, pmsi...)
|
|
private $module;
|
|
|
|
// Nombre de controles activés
|
|
private $nb_realisables;
|
|
|
|
// Prestataire
|
|
private $prestataire;
|
|
|
|
|
|
//********************************************************************************************
|
|
//
|
|
// PUBLIC FUNCTIONS
|
|
//
|
|
//********************************************************************************************/
|
|
|
|
|
|
/**
|
|
* Constructeur
|
|
*
|
|
*/
|
|
function __construct($schema) {
|
|
|
|
$this->ready = false;
|
|
$this->error_msg = '';
|
|
$this->msg = '';
|
|
$this->database = null;
|
|
$this->expert_active = false;
|
|
$this->expert_date_debut = '2013-01-01';
|
|
$this->nb_controls = 0;
|
|
$this->nb_results = 0;
|
|
$this->dictionary = '';
|
|
$this->module = $schema;
|
|
$this->init();
|
|
}
|
|
|
|
|
|
|
|
public function __set($property, $value) {
|
|
if (property_exists($this, $property)) {
|
|
$this->$property = $value;
|
|
}
|
|
return $this;
|
|
}
|
|
|
|
|
|
|
|
public function __get($property) {
|
|
if (property_exists($this, $property)) {
|
|
return $this->$property;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Execute les controles dont la liste est passée en paramètre.
|
|
* Si aucun paramètre n'est passé, tous les contrôles sont exécutés
|
|
*
|
|
* @param $oids : tableau des oid des controles à exécuter
|
|
*/
|
|
public function run_controls($oids=null) {
|
|
|
|
// SI le module expert n'est pas activé, on sort
|
|
if (!$this->expert_active) {
|
|
$this->error_msg = "Le module expert n'est pas activé";
|
|
return false;
|
|
}
|
|
|
|
// Récupère la liste des contrôles si ça n'a pas déjà été fait
|
|
if (count($this->controls) == 0) {
|
|
if (!$this->get_controls($oids)) {
|
|
return false;
|
|
};
|
|
}
|
|
|
|
// EXECUTION DS CONTROLES ----------------------------------------------------------
|
|
|
|
// Nombre de contrôles réalisés avec succès (avec ou sans résultats)
|
|
$nb_succes = 0;
|
|
|
|
// Un contrôle est réalisé s'il est actif et si le prestataire pour lequel il doit s'exécuter est celui configuré dans l'environnement
|
|
$controles_realises = array();
|
|
|
|
// Détermine si on exécute des contrôles précis via une liste d'oids ou si on les exécute tous
|
|
$specific = is_array($oids);
|
|
|
|
foreach($this->controls as $key => $control) {
|
|
// Vérifie si le controle est bien dans la liste des controles à exécuter
|
|
if (!$specific || in_array($control->oid, $oids)) {
|
|
// Vérifie que le contrôle est réalisable (activé et bon prestataire)
|
|
if ($control->realisable) {
|
|
if($control->run()) {
|
|
$nb_succes++;
|
|
}
|
|
else {
|
|
// En cas d'erreur, on récupère le message d'erreur du controle
|
|
$this->error_msg .= $control->error_msg;
|
|
}
|
|
$controles_realises[] = $control->oid;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ECRITURE DES RESULTATS ------------------------------------------------------------
|
|
|
|
|
|
// Désactive les indexes de la table de stockage des résultats
|
|
$i = 0;
|
|
while(++$i < 7) {
|
|
$result = $this->database->exec("SELECT base.cti_disable_index('activite', 'i_expert_sejour_controle_$i')");
|
|
}
|
|
|
|
// Suppression des résultats précédents pour les contrôles exécutés
|
|
if (count($controles_realises) > 0) {
|
|
$request = "DELETE FROM activite.p_expert_sejour_controle WHERE controle_id IN (" . implode(',', $controles_realises) . ")";
|
|
$result = $this->database->exec($request);
|
|
}
|
|
|
|
// Préparation de la requête de stockage des résultats
|
|
$request = "INSERT INTO activite.p_expert_sejour_controle (sejour_id, no_sejour, date_sortie, controle_id, date_signalement, code_justificatif) VALUES ";
|
|
|
|
// Nombre de séjours positifs aux controles experts
|
|
$nb_results = 0;
|
|
// Tableau de mise en forme de chaque résultat
|
|
$values = array();
|
|
|
|
foreach($this->controls as $control_id => $control) {
|
|
|
|
// Mise à jour des infos du controle
|
|
if ($control->last_execution_timestamp != '' && $control->last_execution_ok != '') {
|
|
$update_request = " UPDATE activite.t_expert_controle SET
|
|
last_execution_timestamp = '" . $control->last_execution_timestamp . "'::timestamp,
|
|
last_execution_ok = '" . $control->last_execution_ok . "'
|
|
WHERE oid = " . $control_id . "::bigint;";
|
|
$result = $this->database->exec($update_request);
|
|
if ($result === false) {
|
|
$this->error_msg .= "Impossible de mettre à jour les informations du contrôle " . $control->code . PHP_EOL;
|
|
}
|
|
}
|
|
|
|
// Lecture des résultats de chaque contrôle
|
|
foreach($control->results as $sejour_id => $result) {
|
|
|
|
$nb_results ++;
|
|
|
|
$date_sortie = $result['infos']['date_sortie'];
|
|
$no_sejour = $result['infos']['no_sejour'];
|
|
|
|
$justifs = array();
|
|
foreach($result['justificatifs'] as $name => $justif) {
|
|
$justifs[] = $this->decode_key($name) . self::JUSTIF_SEPARATOR . $justif;
|
|
}
|
|
// S'il y a plusieurs justificatifs, ils seront séparés par une barre verticale
|
|
$code_justificatif = implode(' | ', $justifs);
|
|
$values[] = "(" . $sejour_id . "::bigint, '" . $no_sejour . "'::text, '" . $date_sortie . "'::date, " . $control_id . "::bigint, CURRENT_DATE, '" . $code_justificatif . "'::text)";
|
|
}
|
|
}
|
|
|
|
if ($nb_results > 0) {
|
|
// la commande implode génère une erreur de dépassement de taille mémoire si trop de résultats sont retournés,
|
|
// elle a été remplacée par une boucle sur les résultats
|
|
$request .= implode(', ', $values);
|
|
/*foreach($values as $value) {
|
|
$request .= $value . ', ';
|
|
}
|
|
if (substr($request, -2) == ', ') {
|
|
$request = substr($request, 0, -2);
|
|
}
|
|
*/
|
|
$result = $this->database->exec($request);
|
|
if ($result === false) {
|
|
$this->error_msg = "Impossible de peupler la table des résultats des contrôles";
|
|
}
|
|
}
|
|
|
|
// Ré-active les indexes de la table de stockage des résultats
|
|
$i = 0;
|
|
while(++$i < 7) {
|
|
$result = $this->database->exec("SELECT base.cti_enable_index('activite', 'i_expert_sejour_controle_$i')");
|
|
}
|
|
|
|
|
|
// Nettoyage et rangement de la table des contrôles experts
|
|
$result = $this->database->exec("VACUUM ANALYSE activite.p_expert_sejour_controle;");
|
|
|
|
$pluriel_lances = $this->nb_controls > 1 ? " contrôles lancés, " : " contrôle lancé, ";
|
|
$pluriel_realises = $this->nb_realisables > 1 ? " contrôles réalisés, " : " contrôle réalisé, ";
|
|
$pluriel_resultats = $nb_results > 1 ? " résultats positifs. " : " résultat positif. ";
|
|
$this->msg = PHP_EOL . $this->nb_controls . $pluriel_lances . PHP_EOL . $this->nb_realisables . $pluriel_realises . PHP_EOL . $nb_results . $pluriel_resultats;
|
|
|
|
$this->database->close();
|
|
|
|
if (strlen($this->error_msg) > 0) {
|
|
return false;
|
|
}
|
|
else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Récupère la liste des contrôles expert
|
|
*/
|
|
public function get_controls($oids=null) {
|
|
|
|
$success = true;
|
|
|
|
if (!$this->init()) {
|
|
if($this->error_msg === ''){
|
|
$this->error_msg = 'Initialisation des paramètres des contrôles expert en erreur';
|
|
}
|
|
return false;
|
|
}
|
|
|
|
$this->nb_controls = 0;
|
|
$this->nb_realisables = 0;
|
|
|
|
// Si aucune liste d'oids n'est passsée en paramètre, on récupère tous les contrôles
|
|
$nb_oids = count($oids);
|
|
if ($nb_oids == 1) {
|
|
$where = " AND t_expert_controle.oid =" . $oids[0] . " ";
|
|
}
|
|
else if ($nb_oids > 1) {
|
|
$where = " AND t_expert_controle.oid IN (" . implode(',', $oids) . ") ";
|
|
}
|
|
else {
|
|
$where = "";
|
|
}
|
|
|
|
$request = "
|
|
|
|
SELECT
|
|
t_expert_controle.oid as control_id,
|
|
t_expert_controle.code,
|
|
t_expert_controle.texte,
|
|
t_expert_controle.date_validite_debut,
|
|
t_expert_controle.date_validite_fin,
|
|
t_expert_controle.last_execution_timestamp,
|
|
t_expert_controle.last_execution_ok,
|
|
t_expert_controle.gravite_id as gravite,
|
|
COALESCE(t_expert_controle.etat_cible, 0) as etat_cible,
|
|
t_expert_controle.is_active,
|
|
COALESCE(t_prestataires.alias, 'tous') as prestataire
|
|
FROM
|
|
activite.t_expert_controle
|
|
LEFT JOIN base.t_prestataires ON t_prestataires.oid = t_expert_controle.prestataire_id
|
|
WHERE 1=1
|
|
" . $where;
|
|
$result = $this->database->exec($request);
|
|
if ($result === false) {
|
|
$this->error_msg = 'Erreur pendant la récupération des contrôles. Requête erronée';
|
|
$success = false;
|
|
}
|
|
else {
|
|
while ($row = pg_fetch_array($result)) {
|
|
|
|
$control = new ControleExpert($this->database);
|
|
$control->oid = $row['control_id'];
|
|
$control->code = $row['code'];
|
|
$control->texte = $row['texte'];
|
|
$control->date_validite_debut = $row['date_validite_debut'];
|
|
$control->date_validite_fin = $row['date_validite_fin'];
|
|
$control->last_execution_timestamp = $row['last_execution_timestamp'];
|
|
$control->last_execution_ok = $row['last_execution_ok'];
|
|
$control->gravite = $row['gravite'];
|
|
$control->actif = $row['is_active'] == "1" ? true : false;
|
|
$control->expert_date_debut = $this->expert_date_debut;
|
|
$control->etat_cible = $this->etat_cible[$row['etat_cible']];
|
|
$control->tables = $this->tables;
|
|
$control->prestataire = $row['prestataire'];
|
|
if(!$control->get_rules()) {
|
|
$this->error_msg = 'Impossible de récupérer la liste des règles du contrôle ' . $control->code;
|
|
$success = false;
|
|
break;
|
|
}
|
|
$this->controls[$row['control_id']] = $control;
|
|
$this->nb_controls++;
|
|
// Vérifie que le contrôle est actif et qu'il s'exécute sur le prestataire de l'environnement qui exécute les contrôles
|
|
if ($control->actif && ($control->prestataire == 'tous' || $control->prestataire == $this->prestataire)) {
|
|
$control->realisable = true;
|
|
$this->nb_realisables++;
|
|
}
|
|
else {
|
|
$control->realisable = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $success;
|
|
}
|
|
|
|
|
|
|
|
//********************************************************************************************
|
|
//
|
|
// PRIVATE FUNCTIONS
|
|
//
|
|
//********************************************************************************************/
|
|
|
|
|
|
|
|
private function connect_db() {
|
|
|
|
if (get_class($this->database) != self::DATABASE_CLASS) {
|
|
|
|
$this->database = new Database(self::DATABASE_NAME);
|
|
|
|
if (get_class($this->database) == self::DATABASE_CLASS) {
|
|
return true;
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Remplace le code justificatif par un code à 3 ou 4 lettres plus court.
|
|
* Le dictionnaire de traduction (format JSON) peut/doit être complété
|
|
* modules/base/php/expert/dictionary.json
|
|
*
|
|
* @param $key code à traduire
|
|
*/
|
|
private function decode_key($key) {
|
|
|
|
// Chargement du dictionnaire de traduction des codes des justificatifs si jamais chargé auparavant
|
|
if (!is_array($this->dict_array)) {
|
|
if (file_exists($this->dictionary)) {
|
|
|
|
// Parsage du JSON pour ne récupérer que la section du module qui va bien
|
|
// http://stackoverflow.com/questions/4343596/parsing-json-file-with-php?answertab=votes#tab-top
|
|
$string = file_get_contents($this->dictionary);
|
|
$dict = json_decode($string, true);
|
|
|
|
$jsonIterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($dict), RecursiveIteratorIterator::SELF_FIRST);
|
|
foreach ($jsonIterator as $mod => $entries) {
|
|
if ($mod == $this->module) {
|
|
$this->dict_array = $entries;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$s = strtolower($key);
|
|
|
|
// Parcours du dictionnaire pour remplacer le justificatif
|
|
if (is_array($this->dict_array)) {
|
|
foreach ($this->dict_array as $old => $new) {
|
|
$s = str_replace($old, $new, $s);
|
|
}
|
|
}
|
|
|
|
return $s;
|
|
}
|
|
|
|
|
|
|
|
private function init() {
|
|
|
|
|
|
if ($this->ready) {
|
|
return true;
|
|
}
|
|
else {
|
|
if (!$this->connect_db()) {
|
|
$this->ready = false;
|
|
$this->error_msg = 'Connexion impossible à la base CTI';
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Initialisation des variables
|
|
$this->controls = array();
|
|
$this->ready = true;
|
|
|
|
// Récupération des champs pour les justificatifs.
|
|
// Pour chaque table, on récupère et on stocke le nom de chaque colonne
|
|
// La table fictive 'SQL brut' est ignorée par cette boucle
|
|
foreach($this->tables as $key => $table) {
|
|
if (strlen($table['from']) > 0) {
|
|
$fields = array();
|
|
$request = "SELECT array_to_string(base.cti_array_accum(column_name),'|') AS fields
|
|
FROM
|
|
(
|
|
SELECT column_name::text
|
|
FROM information_schema.columns
|
|
WHERE (table_schema || '.' || table_name) = '" . $table['from'] . "'
|
|
ORDER BY ordinal_position
|
|
) subview";
|
|
$result = $this->database->exec($request);
|
|
if ($result === false) {
|
|
$this->error_msg = 'Récupération des tables _ requête erronée';
|
|
$this->ready = false;
|
|
return false;
|
|
}
|
|
$record = $this->database->nextRecordAssoc();
|
|
$fields = explode("|",trim($record["fields"]));
|
|
$this->tables[$key]['fields'] = $fields;
|
|
}
|
|
}
|
|
|
|
// Initialisation des paramètres Expert
|
|
$request = " INSERT INTO activite.t_divers (code, texte, valeur, description)
|
|
SELECT
|
|
'EXPERT_ACTIVE',
|
|
'Module EXPERT activé',
|
|
'0',
|
|
'1=Activé'
|
|
WHERE 'EXPERT_ACTIVE' NOT IN (SELECT code FROM activite.t_divers); ";
|
|
$result = $this->database->exec($request);
|
|
if ($result === false) {
|
|
$this->error_msg = 'Initilisation des paramètres : Erreur d\'insertion dans la table activite.t_divers';
|
|
}
|
|
|
|
$request = " INSERT INTO activite.t_divers (code, texte, valeur, description, valeur_date)
|
|
SELECT
|
|
'EXPERT_DATE_DEBUT',
|
|
'Date séjours à contrôler',
|
|
'20130101',
|
|
'Date de début des séjours à contrôler',
|
|
'20130101'
|
|
WHERE 'EXPERT_DATE_DEBUT' NOT IN (SELECT code FROM activite.t_divers); ";
|
|
$result = $this->database->exec($request);
|
|
if ($result === false) {
|
|
$this->error_msg = 'Initilisation des paramètres : Erreur d\'insertion de la date de début des séjours à contrôler';
|
|
}
|
|
|
|
// Désactivation controles inutiles
|
|
$request = "
|
|
UPDATE activite.t_expert_controle
|
|
SET is_active = subview.is_active
|
|
FROM
|
|
(
|
|
SELECT t_expert_controle.oid, CASE WHEN MAX(to_id) > 0 THEN '1' ELSE '0' END AS is_active
|
|
FROM activite.t_expert_controle
|
|
JOIN
|
|
(
|
|
SELECT 'CTI_SEJ_AMB_03'::text AS controle_code, 'CTI_UF_AMBU'::text AS liste_code
|
|
UNION
|
|
SELECT 'CTI_MVT_SER_KO', 'CTI_SER_KO'
|
|
UNION
|
|
SELECT 'CTI_MVT_ETA_KO', 'CTI_ETA_KO'
|
|
UNION
|
|
SELECT 'CTI_SEJ_MED_KO', 'CTI_MED_KO'
|
|
) subview
|
|
ON t_expert_controle.code = controle_code
|
|
LEFT JOIN activite.t_listes ON t_listes.code = liste_code
|
|
LEFT JOIN activite.t_listes_contenu ON liste_id = t_listes.oid
|
|
GROUP BY 1
|
|
) subview
|
|
WHERE t_expert_controle.oid = subview.oid AND
|
|
t_expert_controle.is_active <> subview.is_active
|
|
;
|
|
|
|
UPDATE activite.t_expert_controle
|
|
SET is_active = '0'
|
|
WHERE t_expert_controle.code = 'CTI_SEJ_SER_FINESS' AND
|
|
is_active = '1' AND
|
|
(SELECT MAX(finess_id) FROM activite.t_services_facturation ) = 0
|
|
;
|
|
";
|
|
$result = $this->database->exec($request);
|
|
if ($result === false) {
|
|
$this->error_msg = 'Initilisation des paramètres : La désactivation des controles inutiles a échoué';
|
|
}
|
|
|
|
// Ménage / désactivés
|
|
$request = "
|
|
DELETE
|
|
FROM activite.p_expert_sejour_controle
|
|
WHERE controle_id IN (SELECT oid FROM activite.t_expert_controle WHERE is_active <> '1')
|
|
";
|
|
$result = $this->database->exec($request);
|
|
if ($result === false) {
|
|
$this->error_msg = 'Initilisation des paramètres : La suppression des contrôles désactivés a échoué';
|
|
}
|
|
|
|
// Vérification de l'activation du module Expert
|
|
$request = " SELECT * FROM activite.t_divers WHERE code = 'EXPERT_ACTIVE' AND valeur = '1'; ";
|
|
$result = $this->database->exec($request);
|
|
if ($result !== false) {
|
|
if (pg_num_rows($result) == 0) {
|
|
$this->error_msg = 'Module Expert inactif';
|
|
$this->expert_active = false;
|
|
}
|
|
else {
|
|
$this->expert_active = true;
|
|
}
|
|
}
|
|
|
|
// Récupération de la date de départ des controles expert
|
|
$request = " SELECT valeur_date FROM activite.t_divers WHERE code = 'EXPERT_DATE_DEBUT'; ";
|
|
$result = $this->database->exec($request);
|
|
if ($result !== false) {
|
|
while ($row = pg_fetch_array($result)) {
|
|
$this->expert_date_debut = $row['valeur_date'];
|
|
}
|
|
}
|
|
|
|
// Vérification de l'existance de règles
|
|
$request = " SELECT * FROM pmsi.t_expert_controle_rule LIMIT 1; ";
|
|
$result = $this->database->exec($request);
|
|
if ($result !== false && pg_num_rows($result) == 0) {
|
|
$this->error_msg = 'Pas de règles';
|
|
}
|
|
|
|
if (strlen($this->error_msg) > 0) {
|
|
$this->ready = false;
|
|
}
|
|
return $this->ready;
|
|
}
|
|
}
|
|
|
|
?>
|