Fixes retrieval of deceased from AX database.
[platal.git] / modules / fusionax.php
index e5d853d..8a4f9c9 100644 (file)
@@ -33,21 +33,56 @@ class FusionAxModule extends PLModule
 {
     function handlers()
     {
-        return array(
-            'fusionax'          => $this->make_hook('index',    AUTH_MDP, 'admin'),
-            'fusionax/import'   => $this->make_hook('import',   AUTH_MDP, 'admin'),
-            'fusionax/view'     => $this->make_hook('view',     AUTH_MDP, 'admin'),
-            'fusionax/ids'      => $this->make_hook('ids',      AUTH_MDP, 'admin'),
-            'fusionax/deceased' => $this->make_hook('deceased', AUTH_MDP, 'admin'),
-            'fusionax/promo'    => $this->make_hook('promo',    AUTH_MDP, 'admin'),
-        );
+        if (Platal::globals()->merge->state == 'pending') {
+            return array(
+                'fusionax'                  => $this->make_hook('index',    AUTH_MDP, 'admin'),
+                'fusionax/import'           => $this->make_hook('import',   AUTH_MDP, 'admin'),
+                'fusionax/view'             => $this->make_hook('view',     AUTH_MDP, 'admin'),
+                'fusionax/ids'              => $this->make_hook('ids',      AUTH_MDP, 'admin'),
+                'fusionax/deceased'         => $this->make_hook('deceased', AUTH_MDP, 'admin'),
+                'fusionax/promo'            => $this->make_hook('promo',    AUTH_MDP, 'admin'),
+                'fusionax/names'            => $this->make_hook('names',    AUTH_MDP, 'admin'),
+                'fusionax/edu'              => $this->make_hook('edu',      AUTH_MDP, 'admin')
+            );
+        } elseif (Platal::globals()->merge->state == 'done') {
+            return array(
+                'fusionax'                  => $this->make_hook('index',            AUTH_MDP, 'admin,edit_directory'),
+                'fusionax/issues'           => $this->make_hook('issues',           AUTH_MDP, 'admin,edit_directory'),
+                'fusionax/issues/deathdate' => $this->make_hook('issues_deathdate', AUTH_MDP, 'admin,edit_directory'),
+                'fusionax/issues/promo'     => $this->make_hook('issues_promo',     AUTH_MDP, 'admin,edit_directory'),
+            );
+        }
     }
 
 
     function handler_index(&$page)
     {
-        $page->changeTpl('fusionax/index.tpl');
-        $page->assign('xorg_title', 'Polytechnique.org - Fusion des annuaires');
+        if (Platal::globals()->merge->state == 'pending') {
+            $page->changeTpl('fusionax/index.tpl');
+        } elseif (Platal::globals()->merge->state == 'done') {
+            $issueList = array(
+                'name'      => 'noms',
+                'job'       => 'emplois',
+                'address'   => 'adresses',
+                'promo'     => 'promotions',
+                'deathdate' => 'dates de décès',
+                'phone'     => 'téléphones',
+                'education' => 'formations',
+            );
+            $issues = XDB::rawFetchOneAssoc("SELECT  COUNT(*) AS total,
+                                                     SUM(FIND_IN_SET('name', issues))      DIV 1 AS name,
+                                                     SUM(FIND_IN_SET('job', issues))       DIV 2 AS job,
+                                                     SUM(FIND_IN_SET('address', issues))   DIV 3 AS address,
+                                                     SUM(FIND_IN_SET('promo', issues))     DIV 4 AS promo,
+                                                     SUM(FIND_IN_SET('deathdate', issues)) DIV 5 AS deathdate,
+                                                     SUM(FIND_IN_SET('phone', issues))     DIV 6 AS phone,
+                                                     SUM(FIND_IN_SET('education', issues)) DIV 7 AS education
+                                               FROM  profile_merge_issues
+                                              WHERE  issues IS NOT NULL OR issues != ''");
+            $page->changeTpl('fusionax/issues.tpl');
+            $page->assign('issues', $issues);
+            $page->assign('issueList', $issueList);
+        }
     }
 
     /** Import de l'annuaire de l'AX depuis l'export situé dans le home de jacou */
@@ -164,29 +199,29 @@ class FusionAxModule extends PLModule
                 $directoryName = $lastname . ' ' . $firstname;
                 ++$xorgId;
 
-                XDB::execute('REPLACE INTO  profiles (hrpid, xorg_id, ax_id, sex)
-                                    VALUES  ({?}, {?}, {?}, {?})',
+                XDB::execute('INSERT INTO  profiles (hrpid, xorg_id, ax_id, sex)
+                                   VALUES  ({?}, {?}, {?}, {?})',
                              $hrid, $xorgId, $ax_id, $sex);
                 $pid = XDB::insertId();
-                XDB::execute('REPLACE INTO  profile_name (pid, name, typeid)
-                                    VALUES  ({?}, {?}, {?})',
+                XDB::execute('INSERT INTO  profile_name (pid, name, typeid)
+                                   VALUES  ({?}, {?}, {?})',
                              $pid, $lastname, $nameTypes['name_ini']);
-                XDB::execute('REPLACE INTO  profile_name (pid, name, typeid)
-                                    VALUES  ({?}, {?}, {?})',
+                XDB::execute('INSERT INTO  profile_name (pid, name, typeid)
+                                   VALUES  ({?}, {?}, {?})',
                              $pid, $firstname, $nameTypes['firstname_ini']);
-                XDB::execute('REPLACE INTO  profile_display (pid, yourself, public_name, private_name,
-                                                             directory_name, short_name, sort_name, promo)
-                                    VALUES  ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})',
+                XDB::execute('INSERT INTO  profile_display (pid, yourself, public_name, private_name,
+                                                            directory_name, short_name, sort_name, promo)
+                                   VALUES  ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})',
                              $pid, $firstname, $fullName, $fullName, $directoryName, $fullName, $directoryName, $promo);
-                XDB::execute('REPLACE INTO  profile_education (pid, eduid, degreeid, entry_year, grad_year, flags)
-                                    VALUES  ({?}, {?}, {?}, {?}, {?}, {?})',
+                XDB::execute('INSERT INTO  profile_education (pid, eduid, degreeid, entry_year, grad_year, flags)
+                                   VALUES  ({?}, {?}, {?}, {?}, {?}, {?})',
                              $pid, $eduSchools[Profile::EDU_X], $degreeid, $entry_year, $grad_year, 'primary');
-                XDB::execute('REPLACE INTO  accounts (hruid, type, is_admin, state, full_name, directory_name, display_name, sex)
-                                    VALUES  ({?}, {?}, {?}, {?}, {?}, {?}, {?})',
+                XDB::execute('INSERT INTO  accounts (hruid, type, is_admin, state, full_name, directory_name, display_name, sex)
+                                   VALUES  ({?}, {?}, {?}, {?}, {?}, {?}, {?})',
                              $hrid, $type, 0, 'active', $fullName, $directoryName, $lastname, $sex);
                 $uid = XDB::insertId();
-                XDB::execute('REPLACE INTO  account_profiles (uid, pid, perms)
-                                    VALUES  ({?}, {?}, {?})',
+                XDB::execute('INSERT INTO  account_profiles (uid, pid, perms)
+                                   VALUES  ({?}, {?}, {?})',
                              $uid, $pid, 'owner');
             }
             $report[] = 'Promo 1920 ajoutée.';
@@ -220,12 +255,12 @@ class FusionAxModule extends PLModule
         $page->changeTpl('fusionax/view.tpl');
         if ($action == 'create') {
             XDB::execute('DROP VIEW IF EXISTS fusionax_deceased');
-            XDB::execute('CREATE VIEW  fusionax_deceased AS
+            XDB::execute("CREATE VIEW  fusionax_deceased AS
                                SELECT  p.pid, a.ax_id, pd.private_name, pd.promo, p.deathdate AS deces_xorg, a.Date_deces AS deces_ax
                                  FROM  profiles         AS p
                            INNER JOIN  profile_display  AS pd ON (p.pid = pd.pid)
                            INNER JOIN  fusionax_anciens AS a ON (a.ax_id = p.ax_id)
-                                WHERE  p.deathdate != a.Date_deces');
+                                WHERE  p.deathdate != a.Date_deces OR (p.deathdate IS NULL AND a.Date_deces != '0000-00-00')");
             XDB::execute('DROP VIEW IF EXISTS fusionax_promo');
             XDB::execute('CREATE VIEW  fusionax_promo AS
                                SELECT  p.pid, p.ax_id, pd.private_name, pd.promo, pe.entry_year AS promo_etude_xorg,
@@ -419,7 +454,7 @@ class FusionAxModule extends PLModule
         if ($action == 'updateXorg') {
             XDB::execute('UPDATE  fusionax_deceased
                              SET  deces_xorg = deces_ax
-                           WHERE  deces_xorg = "0000-00-00"');
+                           WHERE  deces_xorg IS NULL');
         }
         if ($action == 'updateAX') {
             XDB::execute('UPDATE  fusionax_deceased
@@ -440,7 +475,7 @@ class FusionAxModule extends PLModule
         $page->assign('deceasedErrors', $deceasedErrorsSql->fetchOneCell());
         $res = XDB::iterator('SELECT  pid, ax_id, promo, private_name, deces_ax
                                 FROM  fusionax_deceased
-                               WHERE  deces_xorg = "0000-00-00"
+                               WHERE  deces_xorg IS NULL
                                LIMIT  10');
         $page->assign('nbDeceasedMissingInXorg', $res->total());
         $page->assign('deceasedMissingInXorg', $res);
@@ -462,18 +497,248 @@ class FusionAxModule extends PLModule
         $page->changeTpl('fusionax/promo.tpl');
         $res = XDB::iterator('SELECT  pid, private_name, promo_etude_xorg, promo_sortie_xorg, promo_etude_ax, promo
                                 FROM  fusionax_promo
-                               WHERE  !(promo_etude_ax + 1 = promo_etude_xorg AND promo_etude_xorg + 3 = promo_sortie_xorg)');
+                               WHERE  !(promo_etude_ax + 1 = promo_etude_xorg AND promo_etude_xorg + 3 = promo_sortie_xorg)
+                                      AND !(promo_etude_ax + 1 = promo_etude_xorg AND promo_etude_xorg + 4 = promo_sortie_xorg)
+                                      AND !(promo_etude_ax = promo_etude_xorg + 1)
+                            ORDER BY  promo_etude_xorg');
         $nbMissmatchingPromos = $res->total();
+        $page->assign('nbMissmatchingPromos', $res->total());
+        $page->assign('missmatchingPromos', $res);
+
+        $res = XDB::iterator('SELECT  pid, private_name, promo_etude_xorg, promo_sortie_xorg, promo_etude_ax, promo
+                                FROM  fusionax_promo
+                               WHERE  promo_etude_ax = promo_etude_xorg + 1
+                            ORDER BY  promo_etude_xorg');
+        $nbMissmatchingPromos += $res->total();
         $page->assign('nbMissmatchingPromos1', $res->total());
         $page->assign('missmatchingPromos1', $res);
+
         $res = XDB::iterator('SELECT  pid, private_name, promo_etude_xorg, promo_sortie_xorg, promo_etude_ax, promo
                                 FROM  fusionax_promo
-                               WHERE  promo_etude_ax + 1 = promo_etude_xorg AND promo_etude_xorg + 3 = promo_sortie_xorg');
+                               WHERE  promo_etude_ax + 1 = promo_etude_xorg AND promo_etude_xorg + 3 = promo_sortie_xorg
+                            ORDER BY  promo_etude_xorg');
         $nbMissmatchingPromos += $res->total();
         $page->assign('nbMissmatchingPromos2', $res->total());
         $page->assign('missmatchingPromos2', $res);
-        $page->assign('nbMissmatchingPromos', $nbMissmatchingPromos);
+
+        $res = XDB::iterator('SELECT  pid, private_name, promo_etude_xorg, promo_sortie_xorg, promo_etude_ax, promo
+                                FROM  fusionax_promo
+                               WHERE  promo_etude_ax + 1 = promo_etude_xorg AND promo_etude_xorg + 4 = promo_sortie_xorg
+                            ORDER BY  promo_etude_xorg');
+        $nbMissmatchingPromos += $res->total();
+        $page->assign('nbMissmatchingPromos3', $res->total());
+        $page->assign('missmatchingPromos3', $res);
+
+        $page->assign('nbMissmatchingPromosTotal', $nbMissmatchingPromos);
+    }
+
+    function handler_names(&$page, $action = '')
+    {
+        $page->changeTpl('fusionax/names.tpl');
+
+        $res = XDB::query('SELECT  COUNT(*)
+                             FROM  fusionax_anciens AS f
+                       INNER JOIN  profiles         AS p    ON (f.ax_id = p.ax_id)');
+        $page->assign('total', $res->fetchOneCell());
+
+        // To be checked:
+        // | lastname           |  1 |
+        // | lastname_marital   |  2 |
+        // | lastname_ordinary  |  3 |
+        // | firstname          |  4 |
+        // | firstname_ordinary |  7 |
+        // | firstname_other    |  8 |
+        // | name_other         |  9 |
+        // | name_ini           | 10 |
+        // | firstname_ini      | 11 |
+        $res = XDB::query("SELECT  COUNT(*)
+                             FROM  fusionax_anciens AS f
+                       INNER JOIN  profiles         AS p   ON (f.ax_id = p.ax_id)
+                        LEFT JOIN  profile_name     AS pnp ON (p.pid = pnp.pid AND pnp.typeid = 1)
+                        LEFT JOIN  profile_name     AS pnm ON (p.pid = pnm.pid AND pnm.typeid = 2)
+                        LEFT JOIN  profile_name     AS pno ON (p.pid = pno.pid AND pno.typeid = 3)
+                        LEFT JOIN  profile_name     AS pne ON (p.pid = pne.pid AND pne.typeid = 9)
+                        LEFT JOIN  profile_name     AS pni ON (p.pid = pni.pid AND pni.typeid = 10)
+                            WHERE  IF(f.partic_patro, CONCAT(f.partic_patro, CONCAT(' ', f.Nom_patronymique)), f.Nom_patronymique) NOT IN (pnp.name, pno.name, pnm.name, pne.name, pni.name)
+                                   OR IF(f.partic_nom, CONCAT(f.partic_nom, CONCAT(' ', f.Nom_usuel)), f.Nom_usuel) NOT IN (pnp.name, pno.name, pnm.name, pne.name, pni.name)
+                                   OR f.Nom_complet NOT IN (pnp.name, pno.name, pnm.name, pne.name, pni.name)");
+        $page->assign('lastnameIssues', $res->fetchOneCell());
+
+        $res = XDB::query('SELECT  COUNT(*)
+                             FROM  fusionax_anciens AS f
+                       INNER JOIN  profiles         AS p   ON (f.ax_id = p.ax_id)
+                        LEFT JOIN  profile_name     AS pnf ON (p.pid = pnf.pid AND pnf.typeid = 4)
+                        LEFT JOIN  profile_name     AS pno ON (p.pid = pno.pid AND pno.typeid = 7)
+                        LEFT JOIN  profile_name     AS pne ON (p.pid = pne.pid AND pne.typeid = 8)
+                        LEFT JOIN  profile_name     AS pni ON (p.pid = pni.pid AND pni.typeid = 11)
+                            WHERE  f.prenom NOT IN (pnf.name, pno.name, pne.name, pni.name)');
+        $page->assign('firstnameIssues', $res->fetchOneCell());
+
+    }
+
+    function handler_edu(&$page, $action = '')
+    {
+        $page->changeTpl('fusionax/education.tpl');
+
+        $missingEducation = XDB::rawIterator("SELECT  DISTINCT(f.Intitule_diplome)
+                                                FROM  fusionax_formations AS f
+                                               WHERE  f.Intitule_diplome != '' AND NOT EXISTS (SELECT  *
+                                                                                                 FROM  profile_education_enum AS e
+                                                                                                WHERE  f.Intitule_diplome = e.name)");
+        $missingDegree = XDB::rawIterator("SELECT  DISTINCT(f.Intitule_formation)
+                                             FROM  fusionax_formations AS f
+                                            WHERE  f.Intitule_formation != '' AND NOT EXISTS (SELECT  *
+                                                                                                FROM  profile_education_degree_enum AS e
+                                                                                               WHERE  f.Intitule_formation = e.abbreviation)");
+        $missingCouple = XDB::rawIterator("SELECT  DISTINCT(f.Intitule_diplome) AS edu, f.Intitule_formation AS degree, ee.id AS eduid, de.id AS degreeid
+                                             FROM  fusionax_formations           AS f
+                                       INNER JOIN  profile_education_enum        AS ee ON (f.Intitule_diplome = ee.name)
+                                       INNER JOIN  profile_education_degree_enum AS de ON (f.Intitule_formation = de.abbreviation)
+                                            WHERE  f.Intitule_diplome != '' AND f.Intitule_formation != ''
+                                                   AND NOT EXISTS (SELECT  *
+                                                                     FROM  profile_education_degree AS d
+                                                                    WHERE  ee.id = d.eduid AND de.id = d.degreeid)");
+
+        $page->assign('missingEducation', $missingEducation);
+        $page->assign('missingDegree', $missingDegree);
+        $page->assign('missingCouple', $missingCouple);
+        $page->assign('missingEducationCount', $missingEducation->total());
+        $page->assign('missingDegreeCount', $missingDegree->total());
+        $page->assign('missingCoupleCount', $missingCouple->total());
+    }
+
+    function handler_issues_deathdate(&$page, $action = '')
+    {
+        $page->changeTpl('fusionax/deathdate_issues.tpl');
+        if ($action == 'edit') {
+            S::assert_xsrf_token();
+
+            $issues = XDB::rawIterRow('SELECT  p.pid, pd.directory_name, pd.promo, pm.deathdate_ax, p.deathdate
+                                         FROM  profile_merge_issues AS pm
+                                   INNER JOIN  profiles             AS p  ON (pm.pid = p.pid)
+                                   INNER JOIN  profile_display      AS pd ON (pd.pid = p.pid)
+                                        WHERE  FIND_IN_SET(\'deathdate\', pm.issues)
+                                     ORDER BY  pd.directory_name');
+            while (list($pid, $name, $promo, $deathAX, $deathXorg) = $issues->next()) {
+                $choiceAX = Post::has('AX_' . $pid);
+                $choiceXorg = Post::has('XORG_' . $pid);
+                if (!($choiceAX || $choiceXorg)) {
+                    continue;
+                }
+
+                if ($choiceAX) {
+                    XDB::execute('UPDATE  profiles             AS p
+                              INNER JOIN  profile_merge_issues AS pm ON (pm.pid = p.pid)
+                                     SET  p.deathdate = pm.deathdate_ax, p.deathdate_rec = NOW()
+                                   WHERE  p.pid = {?}', $pid);
+                }
+                XDB::execute("UPDATE  profile_merge_issues
+                                 SET  issues = REPLACE(issues, 'deathdate', '')
+                               WHERE  pid = {?}", $pid());
+                $page->trigSuccess("La date de décès de $name ($promo) a bien été corrigée.");
+            }
+        }
+
+        $issues = XDB::rawFetchAllAssoc('SELECT  p.pid, p.hrpid, pd.directory_name, pd.promo, pm.deathdate_ax, p.deathdate
+                                           FROM  profile_merge_issues AS pm
+                                     INNER JOIN  profiles             AS p  ON (pm.pid = p.pid)
+                                     INNER JOIN  profile_display      AS pd ON (pd.pid = p.pid)
+                                          WHERE  FIND_IN_SET(\'deathdate\', pm.issues)
+                                       ORDER BY  pd.directory_name');
+        $page->assign('issues', $issues);
+        $page->assign('total', count($issues));
+    }
+
+    function handler_issues_promo(&$page, $action = '')
+    {
+        $page->changeTpl('fusionax/promo_issues.tpl');
+        if ($action == 'edit') {
+            S::assert_xsrf_token();
+
+            $issues = XDB::rawIterRow('SELECT  p.pid, pd.directory_name, pd.promo, pm.entry_year_ax, pe.entry_year, pe.grad_year
+                                         FROM  profile_merge_issues AS pm
+                                   INNER JOIN  profiles             AS p  ON (pm.pid = p.pid)
+                                   INNER JOIN  profile_display      AS pd ON (pd.pid = p.pid)
+                                   INNER JOIN  profile_education    AS pe ON (pe.pid = p.pid AND FIND_IN_SET(\'primary\', pe.flags))
+                                        WHERE  FIND_IN_SET(\'promo\', pm.issues)
+                                     ORDER BY  pd.directory_name');
+            while (list($pid, $name, $promo, $deathAX, $deathXorgEntry, $deathXorgGrad) = $issues->next()) {
+                $choiceXorg = Post::has('XORG_' . $pid);
+                if (!(Post::has('display_' . $pid) && Post::has('entry_' . $pid) && Post::has('grad_' . $pid))) {
+                    continue;
+                }
+
+                $display = Post::i('display_' . $pid);
+                $entry = Post::i('entry_' . $pid);
+                $grad = Post::i('grad_' . $pid);
+                if (!(($grad <= $entry + 5 && $grad >= $entry + 3) && ($display >= $entry && $display <= $grad - 3))) {
+                    $page->trigError("La promotion de $name n'a pas été corrigée.");
+                    continue;
+                }
+                XDB::execute('UPDATE  profile_display
+                                 SET  promo = {?}
+                               WHERE  pid = {?}', 'X' . $display, $pid);
+                XDB::execute('UPDATE  profile_education
+                                 SET  entry_year = {?}, grad_year = {?}
+                               WHERE  pid = {?} AND FIND_IN_SET(\'primary\', flags)', $entry, $grad, $pid);
+                $page->trigSuccess("La promotion de $name a bien été corrigée.");
+            }
+        }
+
+        $issues = XDB::rawFetchAllAssoc('SELECT  p.pid, p.hrpid, pd.directory_name, pd.promo, pm.entry_year_ax, pe.entry_year, pe.grad_year
+                                           FROM  profile_merge_issues AS pm
+                                     INNER JOIN  profiles             AS p  ON (pm.pid = p.pid)
+                                     INNER JOIN  profile_display      AS pd ON (pd.pid = p.pid)
+                                     INNER JOIN  profile_education    AS pe ON (pe.pid = p.pid AND FIND_IN_SET(\'primary\', pe.flags))
+                                          WHERE  FIND_IN_SET(\'promo\', pm.issues)
+                                       ORDER BY  pd.directory_name');
+        $page->assign('issues', $issues);
+        $page->assign('total', count($issues));
+    }
+
+    function handler_issues(&$page, $action = '')
+    {
+        static $issueList = array(
+            'name'      => 'noms',
+            'phone'     => 'téléphones',
+            'education' => 'formations',
+            'address'   => 'adresses',
+            'job'       => 'emplois'
+        );
+        static $typeList = array(
+            'name'      => 'general',
+            'phone'     => 'general',
+            'education' => 'general',
+            'address'   => 'adresses',
+            'job'       => 'emploi'
+        );
+
+        if (!array_key_exists($action, $issueList)) {
+            pl_redirect('fusionax');
+        } else {
+            $total = XDB::fetchOneCell('SELECT  COUNT(*)
+                                          FROM  profile_merge_issues
+                                         WHERE  FIND_IN_SET({?}, issues)', $action);
+            if ($total == 0) {
+                pl_redirect('fusionax');
+            }
+
+            $issues = XDB::fetchAllAssoc('SELECT  p.hrpid, pd.directory_name, pd.promo
+                                            FROM  profile_merge_issues AS pm
+                                      INNER JOIN  profiles             AS p  ON (pm.pid = p.pid)
+                                      INNER JOIN  profile_display      AS pd ON (pd.pid = p.pid)
+                                           WHERE  FIND_IN_SET({?}, pm.issues)
+                                        ORDER BY  pd.directory_name
+                                           LIMIT  100', $action);
+
+            $page->changeTpl('fusionax/other_issues.tpl');
+            $page->assign('issues', $issues);
+            $page->assign('issue', $issueList[$action]);
+            $page->assign('type', $typeList[$action]);
+            $page->assign('total', $total);
+        }
     }
 }
 
-// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:?>
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>