Commit d3c6300b authored by Laurent Lécluse's avatar Laurent Lécluse
Browse files

Mise ne CRON des jobs de synchronisation

Ordonnancement des tables
MAJ du SQL de création pour UnicaenImport
parent ec1e41a0
......@@ -3,6 +3,8 @@
namespace UnicaenImport;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
use Zend\ModuleManager\Feature\ConsoleUsageProviderInterface;
use Zend\Console\Adapter\AdapterInterface as ConsoleAdapterInterface;
use Zend\Mvc\MvcEvent;
/**
......@@ -10,7 +12,7 @@ use Zend\Mvc\MvcEvent;
*
* @author Laurent LECLUSE <laurent.lecluse at unicaen.fr>
*/
class Module implements ConfigProviderInterface
class Module implements ConfigProviderInterface, ConsoleUsageProviderInterface
{
public function onBootstrap(MvcEvent $e)
{
......@@ -23,4 +25,14 @@ class Module implements ConfigProviderInterface
{
return include __DIR__ . '/config/module.config.php';
}
public function getConsoleUsage(ConsoleAdapterInterface $console)
{
return [
"Exécution de script",
'UnicaenImport SyncJob <job>' => "Lance un job de synchronisation",
];
}
}
......@@ -24,6 +24,23 @@ return [
],
],
'console' => [
'router' => [
'routes' => [
'unicaen-import' => [
'options' => [
'type' => 'catchall',
'route' => 'UnicaenImport SyncJob <job>',
'defaults' => [
'controller' => 'Import\Controller\Import',
'action' => 'sync-job',
],
],
],
],
],
],
'navigation' => [
'default' => [
'home' => [
......@@ -163,6 +180,7 @@ return [
Service\QueryGeneratorService::class => Service\Factory\QueryGeneratorServiceFactory::class,
Service\DifferentielService::class => Service\Factory\DifferentielServiceFactory::class,
Service\SourceService::class => Service\Factory\SourceServiceFactory::class,
Service\TableService::class => Service\Factory\TableServiceFactory::class,
Processus\ImportProcessus::class => Processus\Factory\ImportProcessusFactory::class,
ORM\Event\Listeners\EntitySourceInjector::class => ORM\Event\Listeners\Factory\EntitySourceInjectorFactory::class,
],
......
......@@ -9,80 +9,102 @@ CREATE TABLE SYNC_LOG
USING INDEX (CREATE UNIQUE INDEX SYNC_LOG_PK ON SYNC_LOG (ID ASC)) ENABLE
);
CREATE TABLE IMPORT_TABLES
(
TABLE_NAME VARCHAR2(30 CHAR) NOT NULL
, SYNC_FILTRE VARCHAR2(2000 CHAR)
, SYNC_ENABLED NUMBER(1, 0) DEFAULT 0 NOT NULL
, SYNC_JOB VARCHAR2(40 CHAR)
, SYNC_HOOK_BEFORE VARCHAR2(4000 CHAR)
, SYNC_HOOK_AFTER VARCHAR2(4000 CHAR)
, ORDRE NUMBER
, CONSTRAINT IMPORT_TABLES_PK PRIMARY KEY (TABLE_NAME)
USING INDEX (CREATE UNIQUE INDEX IMPORT_TABLES_PK ON IMPORT_TABLES (TABLE_NAME ASC)) ENABLE
);
/
create sequence SYNC_LOG_ID_SEQ;
/
CREATE OR REPLACE VIEW "V_IMPORT_TAB_COLS" AS
WITH importable_tables (table_name )AS (
SELECT
t.table_name
FROM
user_tab_cols c
join user_tables t on t.table_name = c.table_name
WHERE
c.column_name = 'SOURCE_CODE'
MINUS
SELECT
mview_name table_name
FROM
USER_MVIEWS
), c_values (table_name, column_name, c_table_name, c_column_name) AS (
SELECT
tc.table_name,
tc.column_name,
pcc.table_name c_table_name,
pcc.column_name c_column_name
FROM
user_tab_cols tc
JOIN USER_CONS_COLUMNS cc ON cc.table_name = tc.table_name AND cc.column_name = tc.column_name
JOIN USER_CONSTRAINTS c ON c.constraint_name = cc.constraint_name
JOIN USER_CONSTRAINTS pc ON pc.constraint_name = c.r_constraint_name
JOIN USER_CONS_COLUMNS pcc ON pcc.constraint_name = pc.constraint_name
WHERE
c.constraint_type = 'R' AND pc.constraint_type = 'P'
)
CREATE OR REPLACE VIEW "V_IMPORT_TAB_COLS" ("TABLE_NAME", "COLUMN_NAME", "DATA_TYPE", "LENGTH", "NULLABLE", "HAS_DEFAULT", "C_TABLE_NAME", "C_COLUMN_NAME", "IMPORT_ACTIF") AS
WITH importable_tables (table_name )AS (
SELECT
tc.table_name,
tc.column_name,
tc.data_type,
CASE WHEN tc.char_length = 0 THEN NULL ELSE tc.char_length END length,
CASE WHEN tc.nullable = 'Y' THEN 1 ELSE 0 END nullable,
CASE WHEN tc.data_default IS NOT NULL THEN 1 ELSE 0 END has_default,
cv.c_table_name,
cv.c_column_name,
CASE WHEN stc.table_name IS NULL THEN 0 ELSE 1 END AS import_actif
FROM
user_tab_cols tc
JOIN importable_tables t ON t.table_name = tc.table_name
LEFT JOIN c_values cv ON cv.table_name = tc.table_name AND cv.column_name = tc.column_name
LEFT JOIN user_tab_cols stc ON stc.table_name = 'SRC_' || tc.table_name AND stc.column_name = tc.column_name
WHERE
tc.column_name not like 'HISTO_%'
ORDER BY
tc.table_name, tc.column_id;
t.table_name
FROM
user_tab_cols c
join user_tables t on t.table_name = c.table_name
WHERE
c.column_name = 'SOURCE_CODE'
MINUS
SELECT
mview_name table_name
FROM
USER_MVIEWS
), c_values (table_name, column_name, c_table_name, c_column_name) AS (
SELECT
tc.table_name,
tc.column_name,
pcc.table_name c_table_name,
pcc.column_name c_column_name
FROM
user_tab_cols tc
JOIN USER_CONS_COLUMNS cc ON cc.table_name = tc.table_name AND cc.column_name = tc.column_name
JOIN USER_CONSTRAINTS c ON c.constraint_name = cc.constraint_name
JOIN USER_CONSTRAINTS pc ON pc.constraint_name = c.r_constraint_name
JOIN USER_CONS_COLUMNS pcc ON pcc.constraint_name = pc.constraint_name
WHERE
c.constraint_type = 'R' AND pc.constraint_type = 'P'
)
SELECT
tc.table_name,
tc.column_name,
tc.data_type,
CASE WHEN tc.char_length = 0 THEN NULL ELSE tc.char_length END length,
CASE WHEN tc.nullable = 'Y' THEN 1 ELSE 0 END nullable,
CASE WHEN tc.data_default IS NOT NULL THEN 1 ELSE 0 END has_default,
cv.c_table_name,
cv.c_column_name,
CASE WHEN stc.table_name IS NULL THEN 0 ELSE 1 END AS import_actif
FROM
user_tab_cols tc
JOIN importable_tables t ON t.table_name = tc.table_name
LEFT JOIN import_tables it ON it.table_name = tc.table_name
LEFT JOIN c_values cv ON cv.table_name = tc.table_name AND cv.column_name = tc.column_name
LEFT JOIN user_tab_cols stc ON stc.table_name = 'SRC_' || tc.table_name AND stc.column_name = tc.column_name
WHERE
tc.column_name not like 'HISTO_%'
AND tc.column_name <> 'ID'
AND tc.table_name <> 'SYNC_LOG'
ORDER BY
it.ordre, tc.table_name, tc.column_id;
/
create or replace PACKAGE UNICAEN_IMPORT AS
z__SYNC_FILRE__z CLOB DEFAULT '';
z__IGNORE_UPD_COLS__z CLOB DEFAULT '';
PROCEDURE set_current_user(p_current_user IN INTEGER);
FUNCTION get_current_user return INTEGER;
FUNCTION get_current_annee RETURN INTEGER;
PROCEDURE set_current_annee (p_current_annee INTEGER);
FUNCTION get_sql_criterion( table_name varchar2, sql_criterion VARCHAR2 ) RETURN CLOB;
FUNCTION IN_COLUMN_LIST( VALEUR VARCHAR2, CHAMPS CLOB ) RETURN NUMERIC;
PROCEDURE REFRESH_MV( mview_name varchar2 );
PROCEDURE SYNC_LOG( message CLOB, table_name VARCHAR2 DEFAULT NULL, source_code VARCHAR2 DEFAULT NULL );
-- AUTOMATIC GENERATION --
PROCEDURE SYNCHRONISATION( table_name VARCHAR2, SYNC_FILRE CLOB DEFAULT '', IGNORE_UPD_COLS CLOB DEFAULT '' );
-- END OF AUTOMATIC GENERATION --
END UNICAEN_IMPORT;
/
......@@ -97,7 +119,7 @@ create or replace PACKAGE BODY UNICAEN_IMPORT AS
FUNCTION get_current_user RETURN INTEGER IS
BEGIN
IF v_current_user IS NULL THEN
v_current_user := NULL; -- A remplacer par l'utilisateur (ID de la table USER) qui sera le créateur ou le modificateur des données
v_current_user := OSE_PARAMETRE.GET_OSE_USER();
END IF;
RETURN v_current_user;
END get_current_user;
......@@ -112,7 +134,7 @@ create or replace PACKAGE BODY UNICAEN_IMPORT AS
FUNCTION get_current_annee RETURN INTEGER IS
BEGIN
IF v_current_annee IS NULL THEN
v_current_annee := NULL; -- A remplacer par l'année d'import souhaitée (si vous avez de l'annualisation de prévue dans votre BDD)
v_current_annee := OSE_PARAMETRE.GET_ANNEE_IMPORT();
END IF;
RETURN v_current_annee;
END get_current_annee;
......@@ -124,30 +146,25 @@ create or replace PACKAGE BODY UNICAEN_IMPORT AS
FUNCTION get_sql_criterion( table_name varchar2, sql_criterion VARCHAR2 ) RETURN CLOB IS
PROCEDURE SYNCHRONISATION( table_name VARCHAR2, SYNC_FILRE CLOB DEFAULT '', IGNORE_UPD_COLS CLOB DEFAULT '' ) IS
ok NUMERIC(1);
BEGIN
IF sql_criterion <> '' OR sql_criterion IS NOT NULL THEN
RETURN sql_criterion;
END IF;
RETURN '';
/* Exemple d'usage :
SELECT COUNT(*) INTO ok FROM import_tables it WHERE it.table_name = SYNCHRONISATION.table_name AND it.sync_enabled = 1 AND rownum = 1;
RETURN CASE table_name
WHEN 'INTERVENANT' THEN -- Met à jour toutes les données sauf le statut, qui sera traité à part
'WHERE IMPORT_ACTION IN (''delete'',''update'',''undelete'')'
WHEN 'AFFECTATION_RECHERCHE' THEN
'WHERE INTERVENANT_ID IS NOT NULL'
IF 1 = ok THEN
z__SYNC_FILRE__z := SYNCHRONISATION.SYNC_FILRE;
z__IGNORE_UPD_COLS__z := SYNCHRONISATION.IGNORE_UPD_COLS;
EXECUTE IMMEDIATE 'BEGIN UNICAEN_IMPORT_AUTOGEN_PROCS__.' || table_name || '(); END;';
END IF;
END;
WHEN 'ADRESSE_INTERVENANT' THEN
'WHERE INTERVENANT_ID IS NOT NULL'
WHEN 'ELEMENT_TAUX_REGIMES' THEN
'WHERE IMPORT_ACTION IN (''delete'',''insert'',''undelete'')'
ELSE
''
END;*/
PROCEDURE REFRESH_MV( mview_name varchar2 ) IS
BEGIN
DBMS_MVIEW.REFRESH(mview_name, 'C');
EXCEPTION WHEN OTHERS THEN
SYNC_LOG( SQLERRM, mview_name );
END;
......@@ -165,14 +182,27 @@ create or replace PACKAGE BODY UNICAEN_IMPORT AS
RETURN 0;
END;
END UNICAEN_IMPORT;
-- AUTOMATIC GENERATION --
/
-- END OF AUTOMATIC GENERATION --
END UNICAEN_IMPORT;
create or replace PACKAGE UNICAEN_IMPORT_AUTOGEN_PROCS__ IS
END UNICAEN_IMPORT_AUTOGEN_PROCS__;
/
create or replace PACKAGE BODY UNICAEN_IMPORT_AUTOGEN_PROCS__ IS
FUNCTION IN_COLUMN_LIST( VALEUR VARCHAR2, CHAMPS CLOB ) RETURN NUMERIC IS
BEGIN
IF REGEXP_LIKE(CHAMPS, '(^|,)[ \t\r\n\v\f]*' || VALEUR || '[ \t\r\n\v\f]*(,|$)') THEN RETURN 1; END IF;
RETURN 0;
END;
END UNICAEN_IMPORT_AUTOGEN_PROCS__;
/
/*********************************************************************************************
* Privilèges
......@@ -199,7 +229,7 @@ insert into PRIVILEGE (ID, CATEGORIE_ID, CODE, LIBELLE, ORDRE) select
PRIVILEGE_ID_SEQ.nextval,
cat.id,
'ecarts',
'Écarts entre les données de l''application et ses sources',
'Écarts',
1
from CATEGORIE_PRIVILEGE cat where code = 'import';
......@@ -209,7 +239,7 @@ insert into PRIVILEGE (ID, CATEGORIE_ID, CODE, LIBELLE, ORDRE) select
PRIVILEGE_ID_SEQ.nextval,
cat.id,
'maj',
'Mise à jour des données à partir de leurs sources',
'Mise à jour',
2
from CATEGORIE_PRIVILEGE cat where code = 'import';
......@@ -219,7 +249,7 @@ insert into PRIVILEGE (ID, CATEGORIE_ID, CODE, LIBELLE, ORDRE) select
PRIVILEGE_ID_SEQ.nextval,
cat.id,
'tbl',
'Tableau de bord principal',
'Tableau de bord',
3
from CATEGORIE_PRIVILEGE cat where code = 'import';
......@@ -229,6 +259,26 @@ insert into PRIVILEGE (ID, CATEGORIE_ID, CODE, LIBELLE, ORDRE) select
PRIVILEGE_ID_SEQ.nextval,
cat.id,
'vues-procedures',
'Mise à jour des vues différentielles et des procédures de mise à jour',
'Gestion des vues et procédures',
4
from CATEGORIE_PRIVILEGE cat where code = 'import';
\ No newline at end of file
from CATEGORIE_PRIVILEGE cat where code = 'import';
/
insert into PRIVILEGE (ID, CATEGORIE_ID, CODE, LIBELLE, ORDRE) select
PRIVILEGE_ID_SEQ.nextval,
cat.id,
'sources-edition',
'Sources (édition)',
5
from CATEGORIE_PRIVILEGE cat where code = 'import';
/
insert into PRIVILEGE (ID, CATEGORIE_ID, CODE, LIBELLE, ORDRE) select
PRIVILEGE_ID_SEQ.nextval,
cat.id,
'sources-visualisation',
'Sources (visualisation)',
6
from CATEGORIE_PRIVILEGE cat where code = 'import';
......@@ -186,4 +186,12 @@ class ImportController extends AbstractActionController
return new MessengerViewModel();
}
public function syncJobAction()
{
$job = $this->getRequest()->getParam('job');
var_dump($job);
}
}
\ No newline at end of file
......@@ -21,10 +21,40 @@ class Table
protected $name;
/**
* @var string
* @var integer
* @ORM\Column(name="ORDRE", type="integer", nullable=true)
*/
protected $ordre;
/**
* @var bool
* @ORM\Column(name="SYNC_ENABLED", type="boolean", nullable=false)
*/
protected $syncEnabled = false;
/**
* @var string|null
* @ORM\Column(name="SYNC_FILTRE", type="string", length=2000, nullable=true)
*/
protected $syncFiltre;
protected $syncFiltre = null;
/**
* @var string|null
* @ORM\Column(name="SYNC_JOB", type="string", length=40, nullable=true)
*/
protected $syncJob = null;
/**
* @var string|null
* @ORM\Column(name="SYNC_HOOK_BEFORE", type="string", length=4000, nullable=true)
*/
protected $syncHookBefore = null;
/**
* @var string|null
* @ORM\Column(name="SYNC_HOOK_AFTER", type="string", length=4000, nullable=true)
*/
protected $syncHookAfter = null;
......@@ -52,6 +82,54 @@ class Table
/**
* @return int
*/
public function getOrdre(): int
{
return $this->ordre;
}
/**
* @param int $ordre
*
* @return Table
*/
public function setOrdre(int $ordre): Table
{
$this->ordre = $ordre;
return $this;
}
/**
* @return bool
*/
public function isSyncEnabled(): bool
{
return $this->syncEnabled;
}
/**
* @param bool $syncEnabled
*
* @return Table
*/
public function setSyncEnabled(bool $syncEnabled): Table
{
$this->syncEnabled = $syncEnabled;
return $this;
}
/**
* @return string
*/
......@@ -74,4 +152,76 @@ class Table
return $this;
}
/**
* @return null|string
*/
public function getSyncJob()
{
return $this->syncJob;
}
/**
* @param null|string $syncJob
*
* @return Table
*/
public function setSyncJob($syncJob): Table
{
$this->syncJob = $syncJob;
return $this;
}
/**
* @return null|string
*/
public function getSyncHookBefore()
{
return $this->syncHookBefore;
}
/**
* @param null|string $syncHookBefore
*
* @return Table
*/
public function setSyncHookBefore($syncHookBefore): Table
{
$this->syncHookBefore = $syncHookBefore;
return $this;
}
/**
* @return null|string
*/
public function getSyncHookAfter()
{
return $this->syncHookAfter;
}
/**
* @param null|string $syncHookAfter
*
* @return Table
*/
public function setSyncHookAfter($syncHookAfter): Table
{
$this->syncHookAfter = $syncHookAfter;
return $this;
}
}
\ No newline at end of file
......@@ -5,6 +5,7 @@ namespace UnicaenImport\Processus\Factory;
use UnicaenImport\Processus\ImportProcessus;
use UnicaenImport\Service\DifferentielService;
use UnicaenImport\Service\QueryGeneratorService;
use UnicaenImport\Service\TableService;
use Zend\ServiceManager\ServiceLocatorInterface as ContainerInterface;
......@@ -27,6 +28,7 @@ class ImportProcessusFactory
{
$processus = new ImportProcessus();
$processus->setServiceQueryGenerator( $container->get(QueryGeneratorService::class));
$processus->setServiceTable($container->get(TableService::class));
return $processus;
}
......
......@@ -4,6 +4,7 @@ namespace UnicaenImport\Processus;
use UnicaenImport\Entity\Differentiel\Query;
use UnicaenImport\Service\Traits\QueryGeneratorServiceAwareTrait;
use UnicaenImport\Service\Traits\TableServiceAwareTrait;
/**
......@@ -14,6 +15,7 @@ use UnicaenImport\Service\Traits\QueryGeneratorServiceAwareTrait;
class ImportProcessus
{
use QueryGeneratorServiceAwareTrait;
use TableServiceAwareTrait;
/**
* Mise à jour de l'existant uniquement
......@@ -76,4 +78,16 @@ class ImportProcessus
return $this;
}
public function syncJob(string $job)
{
$tables = $this->getServiceTable()->getList();
foreach( $tables as $table ){
if ($table->getSyncJob() == $job && $table->isSyncEnabled()){
$this->getServiceQueryGenerator()->execMaj($table);
}
}
}
}
\ No newline at end of file
<?php
namespace UnicaenImport\Service\Factory;
use UnicaenImport\Service\QueryGeneratorService;
use Zend\ServiceManager\ServiceLocatorInterface as ContainerInterface;
use UnicaenImport\Service\TableService;
/**
* Description of TableServiceFactory
*
* @author LECLUSE Laurent <laurent.lecluse at unicaen.fr>
*/
class TableServiceFactory
{
/**
* @param ContainerInterface $container
* @param string $requestedName
* @param array|null $options
*