diff --git a/modules/life_cycle/batch/config/config_garbage_collector.xml.default b/modules/life_cycle/batch/config/config_garbage_collector.xml.default
new file mode 100644
index 0000000000000000000000000000000000000000..22de7cf82a130c3f133d2f1762d666ba7db94ea8
--- /dev/null
+++ b/modules/life_cycle/batch/config/config_garbage_collector.xml.default
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ROOT>
+    <CONFIG>
+        <Lang>fr</Lang> <!-- fr, en-->
+        <MaarchDirectory>/var/www/html/MaarchCourrier/</MaarchDirectory>
+        <LogLevel>INFO</LogLevel> <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <DisplayedLogLevel>INFO</DisplayedLogLevel> <!-- DEBUG, INFO, NOTICE, WARNING, ERROR-->
+        <dateToPurgeDEL>31/12/2019</dateToPurgeDEL> <!-- FORMAT : DD/MM/YYYY date à partir de laquelle on purge en remontant le passé les courriers et PJ supprimées, si vide, ne sera pas purgé -->
+        <dateToPurgeOBS>31/12/2019</dateToPurgeOBS> <!-- FORMAT : DD/MM/YYYY date à partir de laquelle on purge en remontant le passé les PJ obsolètes, si vide, ne sera pas purgé -->
+        <debug>true</debug> <!-- NO PURGE ONLY SIMULATION, entry false to launch the real purge -->
+    </CONFIG>
+    <CONFIG_BASE>
+        <databaseserver>127.0.0.1</databaseserver>
+        <databaseserverport>5432</databaseserverport>
+        <databasetype>POSTGRESQL</databasetype>
+        <databasename>MaarchCourrier</databasename>
+        <databaseuser>maarch</databaseuser>
+        <databasepassword>maarch</databasepassword>
+    </CONFIG_BASE>
+    <LOG4PHP>
+        <enabled>true</enabled>
+        <Log4PhpLogger>loggerTechnique</Log4PhpLogger>
+        <Log4PhpBusinessCode>life_cycle_purge</Log4PhpBusinessCode>
+        <Log4PhpConfigPath>/var/www/html/MaarchCourrier/apps/maarch_entreprise/xml/log4php.xml</Log4PhpConfigPath>
+    </LOG4PHP>
+</ROOT>
diff --git a/modules/life_cycle/batch/load_process_garbage_collector.php b/modules/life_cycle/batch/load_process_garbage_collector.php
new file mode 100644
index 0000000000000000000000000000000000000000..398fced70e3e5aa82474170fec4f406370deba91
--- /dev/null
+++ b/modules/life_cycle/batch/load_process_garbage_collector.php
@@ -0,0 +1,293 @@
+<?php
+
+/**
+* Copyright Maarch since 2008 under licence GPLv3.
+* See LICENCE.txt file at the root folder for more details.
+* This file is part of Maarch software.
+*
+*/
+
+/**
+ * @brief Library to process the garbage_collector
+ *
+ * @file
+ * @author  Laurent Giovannoni  <dev@maarch.org>
+ * @date $date$
+ * @version $Revision$
+ * @ingroup life_cycle
+ */
+
+/**
+* @brief Class to include the file error
+*
+* @ingroup life_cycle
+*/
+class IncludeFileError extends Exception
+{
+    public function __construct($file) 
+    {
+        $this->file = $file;
+        parent :: __construct('Include File \'$file\' is missing!', 1);
+    }
+}
+
+try {
+    include('Maarch_CLITools/ArgsParser.php');
+    include('LoggerLog4php.php');
+    include('Maarch_CLITools/FileHandler.php');
+    include('Maarch_CLITools/ConsoleHandler.php');
+} catch (IncludeFileError $e) {
+    echo 'Maarch_CLITools required ! \n (pear.maarch.org)\n';
+    exit(106);
+}
+include('batch_tools.php');
+// Globals variables definition
+$state = '';
+$configFile = '';
+$MaarchDirectory = '';
+$batchDirectory = '';
+$batchName = 'process_garbage_collector';
+
+$table = '';
+$adrTable = '';
+$view = '';
+$steps = Array();
+$docservers = Array();
+$docserverSourcePath = '';
+$docserverSourceFingerprint = '';
+$databasetype = '';
+$exitCode = 0;
+$running_date = date('Y-m-d H:i:s');
+$func = '';
+$db = '';
+$db2 = '';
+$docserverControler = '';
+$wb = '';
+$docserversFeatures = array();
+$lckFile = '';
+$errorLckFile = '';
+$totalProcessedResources = 0;
+$dateToPurgeDEL =  '';
+$dateToPurgeOBS =  '';
+$log4PhpEnabled = false;
+$resAlreadyDone = false;
+$attachAlreadyDone = false;
+$obsAlreadyDone = false;
+$debug = 'true';
+
+// Defines scripts arguments
+$argsparser = new ArgsParser();
+// The config file
+$argsparser->add_arg(
+    'config', 
+    array(
+        'short' => 'c',
+        'long' => 'config',
+        'mandatory' => true,
+        'help' => 'Config file path is mandatory.',
+    )
+);
+
+$argsparser->add_arg(
+    'mode', 
+    array(
+        'short' => 'm',
+        'long' => 'mode',
+        'mandatory' => true,
+        'help' => 'Mode (count|purge) is mandatory.',
+    )
+);
+
+// The path of the log directory
+$argsparser->add_arg(
+    'logs', 
+    array(
+        'short' => 'logs',
+        'long' => 'logs',
+        'mandatory' => false,
+        'help' => '',
+    )
+);
+// Parsing script options
+try {
+    $options = $argsparser->parse_args($GLOBALS['argv']);
+    // If option = help then options = false and the script continues ...
+    if ($options == false) {
+        exit(0);
+    }
+} catch (MissingArgumentError $e) {
+    if ($e->arg_name == 'config') {
+        echo 'Configuration file missing' . PHP_EOL;
+        exit(101);
+    }
+    if ($e->arg_name == 'mode') {
+        echo 'mode(count|purge) missinng' . PHP_EOL;
+        exit(105);
+    }
+}
+// Log management
+//$GLOBALS['logger'] = new Logger();
+$GLOBALS['logger'] = new Logger4Php();
+$GLOBALS['logger']->set_threshold_level('DEBUG');
+$console = new ConsoleHandler();
+$GLOBALS['logger']->add_handler($console);
+if (!empty($options['logs'])) {
+    if (!is_dir($options['logs'] . '/process_garbage_collector/')) {
+        mkdir($options['logs'] . '/process_garbage_collector/', 0770, true);
+    }
+    $logFile = $options['logs'] . '/process_garbage_collector/'
+        . date('Y-m-d_H-i-s') . '.log';
+} else {
+    if (!is_dir('logs/process_garbage_collector/')) {
+        mkdir('logs/process_garbage_collector/', 0770, true);
+    }
+    $logFile = 'logs/process_garbage_collector/'
+        . date('Y-m-d_H-i-s') . '.log';
+}
+$file = new FileHandler($logFile);
+$GLOBALS['logger']->add_handler($file);
+$GLOBALS['logger']->write('STATE:INIT', 'INFO');
+$txt = '';
+foreach (array_keys($options) as $key) {
+    if (isset($options[$key]) && $options[$key] == false) {
+        $txt .= $key . '=false,';
+    } else {
+        $txt .= $key . '=' . $options[$key] . ',';
+    }
+}
+$GLOBALS['logger']->write($txt, 'DEBUG');
+$GLOBALS['configFile'] = $options['config'];
+$GLOBALS['logger']->write($txt, 'INFO');
+// Tests existence of config file
+if (!file_exists($GLOBALS['configFile'])) {
+    $GLOBALS['logger']->write('Configuration file ' . $GLOBALS['configFile'] 
+                              . ' does not exist', 'ERROR', 102);
+    exit(102);
+}
+// Loading config file
+$GLOBALS['logger']->write('Load xml config file:' . $GLOBALS['configFile'], 
+                          'INFO');
+$xmlconfig = simplexml_load_file($GLOBALS['configFile']);
+if ($xmlconfig == FALSE) {
+    $GLOBALS['logger']->write('Error on loading config file:' 
+                              . $GLOBALS['configFile'], 'ERROR', 103);
+    exit(103);
+}
+
+$GLOBALS['mode'] = $options['mode'];
+if (
+       strtolower($GLOBALS['mode']) <> 'count' 
+    && strtolower($GLOBALS['mode']) <> 'purge'
+) {
+    $GLOBALS['logger']->write('Error on mode, must be count or purge:' 
+                              . $GLOBALS['mode'], 'ERROR', 105);
+    exit(105);
+}
+// Load the config vars
+$CONFIG = $xmlconfig->CONFIG;
+$lang = (string) $CONFIG->Lang;
+$GLOBALS['MaarchDirectory'] = (string) $CONFIG->MaarchDirectory;
+$GLOBALS['batchDirectory'] = $GLOBALS['MaarchDirectory'] . 'modules/life_cycle/batch/';
+$logLevel = (string) $CONFIG->LogLevel;
+$GLOBALS['logger']->set_threshold_level($logLevel);
+$DisplayedLogLevel = (string) $CONFIG->DisplayedLogLevel;
+$GLOBALS['databasetype'] = (string) $xmlconfig->CONFIG_BASE->databasetype;
+$GLOBALS['dateToPurgeDEL'] = (string) $CONFIG->dateToPurgeDEL;
+$GLOBALS['dateToPurgeOBS'] = (string) $CONFIG->dateToPurgeOBS;
+$GLOBALS['debug'] = (string) $CONFIG->debug;
+if (empty($GLOBALS['debug'])) {
+    $GLOBALS['debug'] = 'true';
+}
+
+if (empty($GLOBALS['dateToPurgeDEL']) && empty($GLOBALS['dateToPurgeOBS'])) {
+    $GLOBALS['logger']->write('dateToPurgeDEL or dateToPurgeOBS must be filled', 'ERROR', 1);
+    exit(105);
+}
+
+$i = 0;
+set_include_path(get_include_path() . PATH_SEPARATOR 
+    . $GLOBALS['MaarchDirectory']);
+//log4php params
+$log4phpParams = $xmlconfig->LOG4PHP;
+if ((string) $log4phpParams->enabled == 'true') {
+    $GLOBALS['logger']->set_log4PhpLibrary(
+        $GLOBALS['MaarchDirectory'] 
+            . 'apps/maarch_entreprise/tools/log4php/Logger.php'
+    );
+    $GLOBALS['logger']->set_log4PhpLogger((string) $log4phpParams->Log4PhpLogger);
+    $GLOBALS['logger']->set_log4PhpBusinessCode((string) $log4phpParams->Log4PhpBusinessCode);
+    $GLOBALS['logger']->set_log4PhpConfigPath((string) $log4phpParams->Log4PhpConfigPath);
+    $GLOBALS['logger']->set_log4PhpBatchName('life_cycle_process_garbage_collector');
+}
+
+if ($logLevel == 'DEBUG') {
+    error_reporting(E_ALL);
+}
+$GLOBALS['logger']->change_handler_log_level($file, $logLevel);
+$GLOBALS['logger']->change_handler_log_level($console, $DisplayedLogLevel);
+unset($xmlconfig);
+
+// Include library
+try {
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/class/class_functions.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/class/class_db_pdo.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/class/class_db.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/class/class_core_tools.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/core_tables.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/class/docservers_controler.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/docservers_tools.php');
+    Bt_myInclude($GLOBALS['MaarchDirectory'] . 'core/class/docserver_types_controler.php');
+} catch (IncludeFileError $e) {
+    $GLOBALS['logger']->write(
+        'Problem with the php include path:' 
+        . get_include_path(), 'ERROR', 111
+    );
+    exit(111);
+}
+
+$coreTools = new core_tools();
+$coreTools->load_lang($lang, $GLOBALS['MaarchDirectory'], 'maarch_entreprise');
+session_start();
+$_SESSION['modules_loaded'] = array();
+$GLOBALS['func'] = new functions();
+$GLOBALS['db'] = new Database($GLOBALS['configFile']);
+$GLOBALS['db2'] = new Database($GLOBALS['configFile']);
+$GLOBALS['dbLog'] = new Database($GLOBALS['configFile']);
+$GLOBALS['docserverControler'] = new docservers_controler();
+$GLOBALS['errorLckFile'] = $GLOBALS['batchDirectory'] . '/' 
+                         . $GLOBALS['batchName'] . '_error.lck';
+$GLOBALS['lckFile'] = $GLOBALS['batchDirectory'] . '/' 
+                    . $GLOBALS['batchName'] . '.lck';
+if (file_exists($GLOBALS['errorLckFile'])) {
+    $GLOBALS['logger']->write(
+        'Error persists, please solve this before launching a new batch', 
+        'ERROR', 29
+    );
+    exit(29);
+}
+if (file_exists($GLOBALS['lckFile'])) {
+    $GLOBALS['logger']->write(
+        'An instance of the garbage_collector batch : is already in progress',
+        'ERROR', 109
+    );
+    exit(109);
+}
+$semaphore = fopen($GLOBALS['lckFile'], 'a');
+fwrite($semaphore, '1');
+fclose($semaphore);
+Bt_getWorkBatch();
+
+$GLOBALS['wb'] = rand() . $GLOBALS['wbCompute'];
+Bt_updateWorkBatch();
+$GLOBALS['logger']->write('Batch number:' . $GLOBALS['wb'], 'INFO');
+
+if (strtolower($GLOBALS['mode']) == 'purge') {
+    if (strtolower($GLOBALS['debug']) == 'false') {
+        $GLOBALS['logger']->write('YOUR ARE NOT IN DEBUG MODE, DATA WILL BE ERASED', 'INFO');
+    } else {
+        $GLOBALS['logger']->write('your are in debug mode', 'INFO');
+    }
+} else {
+    $GLOBALS['logger']->write('your are in count mode', 'INFO');
+}
+
diff --git a/modules/life_cycle/batch/process_garbage_collector.php b/modules/life_cycle/batch/process_garbage_collector.php
new file mode 100644
index 0000000000000000000000000000000000000000..a29ce3c1ed281c2f7bb408e7b1a987f6473940fa
--- /dev/null
+++ b/modules/life_cycle/batch/process_garbage_collector.php
@@ -0,0 +1,446 @@
+<?php
+
+/**
+* Copyright Maarch since 2008 under licence GPLv3.
+* See LICENCE.txt file at the root folder for more details.
+* This file is part of Maarch software.
+*
+*/
+
+/**
+ * @brief Batch to process garbage_collector
+ *
+ * @file
+ * @author  Laurent Giovannoni  <dev@maarch.org>
+ * @date $date$
+ * @version $Revision$
+ * @ingroup life_cycle
+ */
+
+/*****************************************************************************
+WARNING : THIS BATCH ERASE RESOURCES IN DATABASE AND IN DOCSERVERS 
+Please note this batch deletes resources in the database 
+and storage spaces (docservers). 
+You need to run only if it is set -> Make especially careful to 
+define the where clause.
+FOR THE CASE OF AIP : to be used only if the AIP are single resources.
+*****************************************************************************/
+
+/**
+ * *****   LIGHT PROBLEMS without an error semaphore
+ *  101 : Configuration file missing
+ *  102 : Configuration file does not exist
+ *  103 : Error on loading config file
+ *  104 : SQL Query Error
+ *  105 : a parameter is missing
+ *  106 : Maarch_CLITools is missing
+ *  107 : Stack empty for the request
+ *  108 : There are still documents to be processed
+ *  109 : An instance of the batch for the required policy and cyle is already
+ *        in progress
+ *  111 : Problem with the php include path
+ *  112 : AIP not able to be purged
+ *  113 : Security problem with where clause
+ * ****   HEAVY PROBLEMS with an error semaphore
+ *  13  : Docserver not found
+ */
+
+date_default_timezone_set('Europe/Paris');
+try {
+    include('load_process_garbage_collector.php');
+} catch (IncludeFileError $e) {
+    echo "Maarch_CLITools required ! \n (pear.maarch.org)\n";
+    exit(106);
+}
+
+/******************************************************************************/
+/* beginning */
+
+$GLOBALS['state'] = "SELECT_RES";
+$resourcesArrayGLOBAL = array();
+$resourcesArray = array();
+
+while ($GLOBALS['state'] <> "END") {
+    if (isset($GLOBALS['logger'])) {
+        $GLOBALS['logger']->write("STATE:" . $GLOBALS['state'], 'DEBUG');
+    }
+    switch($GLOBALS['state']) {
+        /**********************************************************************/
+        /*                          SELECT_RES                                */
+        /*                                                                    */
+        /**********************************************************************/
+        case 'SELECT_RES' :
+            if (isset($GLOBALS['dateToPurgeDEL']) && !empty($GLOBALS['dateToPurgeDEL'])) {
+                //$where_clause = "STATUS = 'DEL' and creation_date <= '" . $GLOBALS['dateToPurgeDEL'] . "'";
+                // ONLY FOR TEST
+                $where_clause = "creation_date <= '" . $GLOBALS['dateToPurgeDEL'] . "'";
+                if ($GLOBALS['resAlreadyDone']) {
+                    echo 'attach turn' . PHP_EOL;
+                    //SECOND SELECT THE ATTACH IN DEL STATUS
+                    $GLOBALS['table'] = 'res_attachments';
+                    $GLOBALS['exTable'] = '';
+                    $GLOBALS['versionTable'] = 'res_version_attachments';
+                    $GLOBALS['adrTable'] = 'adr_attachments';
+                    $GLOBALS['attachAlreadyDone'] = true;
+                    $GLOBALS['dateToPurgeDEL'] = '';
+                } else {
+                    echo 'res turn' . PHP_EOL;
+                    //FIRST SELECT THE DOC IN DEL STATUS
+                    $GLOBALS['table'] = 'res_letterbox';
+                    $GLOBALS['exTable'] = 'mlb_coll_ext';
+                    $GLOBALS['versionTable'] = '';
+                    $GLOBALS['adrTable'] = 'adr_letterbox';
+                    $GLOBALS['resAlreadyDone'] = true;
+                }
+                if(!$GLOBALS['resAlreadyDone'] && !$GLOBALS['attachAlreadyDone']) {
+                    echo 'resAlreadyDone and attachAlreadyDone' . PHP_EOL;
+                    $state = 'SELECT_RES';
+                    break;
+                }
+            } elseif (isset($GLOBALS['dateToPurgeOBS']) && !empty($GLOBALS['dateToPurgeOBS'])) {
+                echo 'obs turn' . PHP_EOL;
+                //THIRD SELECT THE ATTACH IN OBS STATUS
+                $where_clause = "STATUS = 'OBS' and creation_date <= '" . $GLOBALS['dateToPurgeOBS'] . "'";
+                $GLOBALS['table'] = 'res_attachments';
+                $GLOBALS['exTable'] = '';
+                $GLOBALS['versionTable'] = 'res_version_attachments';
+                $GLOBALS['adrTable'] = 'adr_attachments';
+                $GLOBALS['obsAlreadyDone'] = true;
+                $GLOBALS['dateToPurgeOBS'] = '';
+            } else {
+                echo 'END OF TURNS' . PHP_EOL;
+                $GLOBALS['resAlreadyDone'] = true;
+                $GLOBALS['attachAlreadyDone'] = true;
+                $GLOBALS['obsAlreadyDone'] = true;
+                if (strtolower($GLOBALS['mode']) == 'purge') {
+                    if ($GLOBALS['resAlreadyDone'] && $GLOBALS['attachAlreadyDone'] && $GLOBALS['obsAlreadyDone']) {
+                        $state = 'DELETE_RES_ON_FS';
+                        //var_dump($resourcesArray);
+                    } else {
+                        $state = 'SELECT_RES';
+                    }
+                } elseif (strtolower($GLOBALS['mode']) == 'count') {
+                    if ($GLOBALS['resAlreadyDone'] && $GLOBALS['attachAlreadyDone'] && $GLOBALS['obsAlreadyDone']) {
+                        $state = 'END';
+                        //var_dump($resourcesArray);
+                    } else {
+                        $state = 'SELECT_RES';
+                    }
+                }
+                break;
+            }
+            $orderBy = 'order by res_id';
+            
+            $query = "select res_id, docserver_id, path, filename, fingerprint from " 
+                . $GLOBALS['table'] 
+                . " where " . $where_clause . " " . $orderBy;
+            $stmt = Bt_doQuery($GLOBALS['db'], $query);
+            $GLOBALS['logger']->write('select res query:' . $query, 'INFO');
+            // $resourcesArray = array();
+            if ($stmt->rowCount() > 0) {
+                while ($resoucesRecordset = $stmt->fetchObject()) {
+                    $queryDs = "select path_template from docservers " 
+                       . " where docserver_id = ?";
+                    $stmt2 = Bt_doQuery(
+                        $GLOBALS['db2'], 
+                        $queryDs, 
+                        array($resoucesRecordset->docserver_id)
+                    );
+                    if ($stmt2->rowCount() == 0) {
+                        Bt_exitBatch(13, 'Docserver:' 
+                            . $resoucesRecordset->docserver_id . ' not found');
+                        break;
+                    } else {
+                        $dsRecordset = $stmt2->fetchObject();
+                        $dsPath = $dsRecordset->path_template;
+                    }
+                    array_push(
+                        $resourcesArray,
+                        array(
+                            'res_id' => $resoucesRecordset->res_id,
+                            'table' => $GLOBALS['table'],
+                            'ext_table' => $GLOBALS['extTable'],
+                            'version_table' => $GLOBALS['versionTable'],
+                            'docserver_id' => $resoucesRecordset->docserver_id,
+                            'path_template' => $dsPath,
+                            'path' =>  str_replace('#', DIRECTORY_SEPARATOR, 
+                                $resoucesRecordset->path),
+                            'filename' => $resoucesRecordset->filename,
+                            'fingerprint' => $resoucesRecordset->fingerprint,
+                            'adr' => array(),
+                        )
+                    );
+                    $GLOBALS['totalProcessedResources']++;
+                }
+            } else {
+                // Bt_exitBatch(111, 'no resource found for where clause:' 
+                //     . str_replace("'", "''", $GLOBALS['whereClause']));
+                break;
+            }
+            
+            $queryIsAdr = "select 1 as adr_exists FROM information_schema.tables WHERE table_name = ?";
+            $stmt = Bt_doQuery(
+                $GLOBALS['db'], 
+                $queryIsAdr,
+                array($GLOBALS['adrTable'])
+            );
+            $adrExists = $stmt->fetchObject();
+            if ($adrExists->adr_exists) {
+                $countRA = count($resourcesArray);
+                for ($cptRes = 0;$cptRes < $countRA;$cptRes++) {
+                    $queryAip = "select res_id, docserver_id, path, filename, fingerprint from " 
+                        . $GLOBALS['adrTable']
+                        . " where res_id = ?";
+                    $stmt = Bt_doQuery(
+                        $GLOBALS['db'], 
+                        $queryAip,
+                        array($resourcesArray[$cptRes]["res_id"])
+                    );
+                    if ($stmt->rowCount() > 0) {
+                        while ($resoucesRecordsetAdr = $stmt->fetchObject()) {
+                            $queryDs = "select path_template from docservers " 
+                               . " where docserver_id = ?";
+                            $stmt2 = Bt_doQuery(
+                                $GLOBALS['db2'], 
+                                $queryDs,
+                                array($resoucesRecordsetAdr->docserver_id)
+                            );
+                            if ($stmt2->rowCount() == 0) {
+                                Bt_exitBatch(13, 'Docserver:' 
+                                    . $resoucesRecordsetAdr->docserver_id . ' not found');
+                                break;
+                            } else {
+                                $dsRecordset = $stmt2->fetchObject();
+                                $dsPath = $dsRecordset->path_template;
+                            }
+                            array_push($resourcesArray[$cptRes]['adr'], array(
+                                    'res_id' => $resoucesRecordsetAdr->res_id,
+                                    'adr_table' => $GLOBALS['adrTable'],
+                                    'docserver_id' => $resoucesRecordsetAdr->docserver_id,
+                                    'path_template' => $dsPath,
+                                    'path' => str_replace('#', DIRECTORY_SEPARATOR, 
+                                        $resoucesRecordsetAdr->path),
+                                    'filename' => $resoucesRecordsetAdr->filename,
+                                    'fingerprint' => $resoucesRecordsetAdr->fingerprint,
+                                )
+                            );
+                        }
+                    }
+                    //history
+                    // $query = "insert into " . HISTORY_TABLE
+                    //        . " (table_name, record_id, event_type, user_id, "
+                    //        . "event_date, info, id_module) values (?, ?, 'ADD', 'PURGE_BOT', '"
+                    //        . date("d") . "/" . date("m") . "/" . date("Y") . " " . date("H") 
+                    //        . ":" . date("i") . ":" . date("s")
+                    //        . "', ?, 'life_cyle')";
+                    // $stmt = Bt_doQuery(
+                    //     $GLOBALS['db'], 
+                    //     $query,
+                    //     array(
+                    //         $GLOBALS['table'],
+                    //         $resourcesArray[$cptRes]["res_id"],
+                    //         "purge, where clause:" 
+                    //             . str_replace("'", "''", $GLOBALS['whereClause'])
+                    //     )
+                    // );
+                }
+            }
+            //print_r($resourcesArray);
+            if (strtolower($GLOBALS['mode']) == 'purge') {
+                if ($GLOBALS['resAlreadyDone'] && $GLOBALS['attachAlreadyDone'] && $GLOBALS['obsAlreadyDone']) {
+                    echo 'END OF TURNS' . PHP_EOL;
+                    $state = 'DELETE_RES_ON_FS';
+                    // var_dump($resourcesArray);
+                } else {
+                    $state = 'SELECT_RES';
+                }
+            } elseif (strtolower($GLOBALS['mode']) == 'count') {
+                if ($GLOBALS['resAlreadyDone'] && $GLOBALS['attachAlreadyDone'] && $GLOBALS['obsAlreadyDone']) {
+                    $state = 'END';
+                    echo 'END OF TURNS' . PHP_EOL;
+                    // var_dump($resourcesArray);
+                } else {
+                    $state = 'SELECT_RES';
+                }
+            }
+            
+            break;
+        /**********************************************************************/
+        /*                          DELETE_RES_ON_FS                          */
+        /*                                                                    */
+        /**********************************************************************/
+        case "DELETE_RES_ON_FS" :
+            //var_dump($resourcesArray);
+            if (strtolower($GLOBALS['debug']) == 'true') {
+                $action = 'nothing';
+            } elseif (strtolower($GLOBALS['debug']) == 'false') {
+                $action = 'erase';
+            } else {
+                $action = 'nothing';
+            }
+            $cptRes = 0;
+            $countRA = count($resourcesArray);
+            for ($cptRes = 0;$cptRes < $countRA;$cptRes++) {
+                $GLOBALS['logger']->write('Prepare file deletion for res_id:' 
+                    . $resourcesArray[$cptRes]["res_id"] 
+                    . 'on table:' . $resourcesArray[$cptRes]['table'], 'INFO');
+                $countAdr = count($resourcesArray[$cptRes]['adr']);
+                if ($countAdr > 0) {
+                    $cptAdr = 0;
+                    for ($cptAdr = 0;$cptAdr < $countAdr;$cptAdr++) {
+                        $path = $resourcesArray[$cptRes]['adr'][$cptAdr]['path_template'] 
+                            . $resourcesArray[$cptRes]['adr'][$cptAdr]['path']
+                            . $resourcesArray[$cptRes]['adr'][$cptAdr]['filename'];
+                        echo $path . PHP_EOL;
+                        if (file_exists($path) && is_file($path)) {
+                            if ($action == 'erase') {
+                                unlink($path);
+                            } else {
+                                echo 'debug mode, no erase of file:' . $path;
+                            }
+                        } else {
+                            $GLOBALS['logger']->write('File for res_id ' 
+                                . $resourcesArray[$cptRes]['res_id']
+                                . 'on table:' . $resourcesArray[$cptRes]['table'] 
+                                . ' not exits : '
+                                . $path, 'WARNING');
+                        }
+                    }
+                } else {
+                    $path = $resourcesArray[$cptRes]['path_template'] 
+                          . $resourcesArray[$cptRes]['path']
+                          . $resourcesArray[$cptRes]['filename'];
+                    echo $path . PHP_EOL;
+                    if (file_exists($path) && is_file($path)) {
+                        if ($action == 'erase') {
+                                unlink($path);
+                            } else {
+                                echo 'debug mode, no erase of file:' . $path;
+                            }
+                    } else {
+                        $GLOBALS['logger']->write('File for res_id ' 
+                            . $resourcesArray[$cptRes]['res_id'] 
+                            . 'on table:' . $resourcesArray[$cptRes]['table']
+                            . ' not exits : '
+                            . $path, 'WARNING');
+                    }
+                }
+            }
+            $state = 'DELETE_RES_ON_DB';
+            break;
+        /**********************************************************************/
+        /*                          DELETE_RES_ON_DB                          */
+        /*                                                                    */
+        /**********************************************************************/
+        case "DELETE_RES_ON_DB" :
+
+            for ($cptRes = 0;$cptRes < $countRA;$cptRes++) {
+
+                if (strtolower($GLOBALS['debug']) == 'true') {
+                    $action = 'SELECT';
+                } elseif (strtolower($GLOBALS['debug']) == 'false') {
+                    $action = 'DELETE';
+                } else {
+                    $action = 'SELECT';
+                }
+               
+                $deleteResQuery = "$action FROM " . $resourcesArray[$cptRes]['table']
+                   . " WHERE res_id = ?";
+                $stmt = Bt_doQuery(
+                    $GLOBALS['db'], 
+                    $deleteResQuery,
+                    array($resourcesArray[$cptRes]["res_id"])
+                );
+
+                if ($resourcesArray[$cptRes]['ext_table'] <> "") {
+                    $deleteExtQuery = "$action FROM " . $resourcesArray[$cptRes]['ext_table']
+                       . " WHERE res_id = ?";
+                    $stmt = Bt_doQuery(
+                        $GLOBALS['db'], 
+                        $deleteExtQuery,
+                        array($resourcesArray[$cptRes]["res_id"])
+                    );
+                }
+
+                if ($resourcesArray[$cptRes]['version_table'] <> "") {
+                    $deleteVersionQuery = "$action FROM " . $resourcesArray[$cptRes]['version_table']
+                       . " WHERE res_id_master = ?";
+                    $stmt = Bt_doQuery(
+                        $GLOBALS['db'], 
+                        $deleteVersionQuery,
+                        array($resourcesArray[$cptRes]["res_id"])
+                    );
+                }
+
+                if ($resourcesArray[$cptRes]['adr']['adr_table'] <> "") {
+                    $deleteAdrQuery = "$action FROM " . $resourcesArray[$cptRes]['adr']['adr_table']
+                       . " WHERE res_id = ?";
+                    $stmt = Bt_doQuery(
+                        $GLOBALS['db'], 
+                        $deleteAdrQuery,
+                        array($resourcesArray[$cptRes]["res_id"])
+                    );
+                }
+
+                if ($resourcesArray[$cptRes]['table'] == 'res_letterbox') {
+                    $deleteAdrQuery = "$action FROM contacts_res WHERE res_id = ?";
+                    $stmt = Bt_doQuery(
+                        $GLOBALS['db'], 
+                        $deleteAdrQuery,
+                        array($resourcesArray[$cptRes]["res_id"])
+                    );
+                
+                    $deleteNotesQuery = "$action FROM notes "
+                       . " WHERE identifier = ?";
+                    $stmt = Bt_doQuery(
+                        $GLOBALS['db'], 
+                        $deleteNotesQuery, 
+                        array(
+                            $resourcesArray[$cptRes]["res_id"]
+                        )
+                    );
+
+                    $deleteLinkedQuery = "$action FROM res_linked "
+                       . " WHERE (res_child = ? or res_parent = ?)";
+                    $stmt = Bt_doQuery(
+                        $GLOBALS['db'], 
+                        $deleteLinkedQuery, 
+                        array(
+                            $resourcesArray[$cptRes]["res_id"],
+                            $resourcesArray[$cptRes]["res_id"]
+                        )
+                    );
+
+                    $deleteAttachmentsQuery = "$action FROM res_attachments "
+                       . " WHERE res_id_master = ?";
+                    $stmt = Bt_doQuery(
+                        $GLOBALS['db'], 
+                        $deleteAttachmentsQuery, 
+                        array(
+                            $resourcesArray[$cptRes]["res_id"]
+                        )
+                    );
+
+                    $deleteCasesQuery = "$action FROM cases_res "
+                       . " WHERE res_id = ? ";
+                    $stmt = Bt_doQuery(
+                        $GLOBALS['db'], 
+                        $deleteCasesQuery, 
+                        array($resourcesArray[$cptRes]["res_id"])
+                    );
+                }
+            }
+
+            $state = 'END';
+
+            break;
+    }
+}
+//var_dump($resourcesArray);
+$GLOBALS['logger']->write('End of process for ' 
+    . $GLOBALS['totalProcessedResources'] . ' files. In mode ' . $GLOBALS['mode'], 'INFO');
+Bt_logInDataBase(
+    $GLOBALS['totalProcessedResources'], 0, 'process without error'
+);
+unlink($GLOBALS['lckFile']);
+exit($GLOBALS['exitCode']);
diff --git a/modules/life_cycle/batch/scripts/garbage_collector.sh.default b/modules/life_cycle/batch/scripts/garbage_collector.sh.default
new file mode 100644
index 0000000000000000000000000000000000000000..1f9c5d029e910acae9ba618c13c394e7c722dcba
--- /dev/null
+++ b/modules/life_cycle/batch/scripts/garbage_collector.sh.default
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+path='/var/www/html/MaarchCourrier/modules/life_cycle/batch'
+cd $path
+php  'process_garbage_collector.php' -c /var/www/html/MaarchCourrier/modules/life_cycle/batch/config/config_garbage_collector.xml -m count