diff --git a/modules/convert/Controllers/ProcessManageConvertController.php b/modules/convert/Controllers/ProcessManageConvertController.php
new file mode 100644
index 0000000000000000000000000000000000000000..4d8964681b90ff901e60443e140baff5a96ff719
--- /dev/null
+++ b/modules/convert/Controllers/ProcessManageConvertController.php
@@ -0,0 +1,222 @@
+<?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 process manageConvert class
+*
+* <ul>
+* <li>Services to process the management of convertion of resources</li>
+* </ul>
+*
+* @file
+* @author Laurent Giovannoni <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+namespace Convert\Controllers;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Respect\Validation\Validator;
+use Convert\Controllers\ProcessConvertController;
+use Convert\Controllers\ProcessFulltextController;
+use Convert\Controllers\ProcessThumbnailsController;
+use Core\Controllers\LogsController;
+
+class ProcessManageConvertController
+{
+    protected $libreOfficeExecutable;
+
+    //public function __construct($libreOfficeExecutable = 'cloudooo')
+    public function __construct($libreOfficeExecutable = 'soffice')
+    //public function __construct($libreOfficeExecutable = 'unoconv')
+    {
+        $this->libreOfficeExecutable = $libreOfficeExecutable;
+    }
+
+    public function create(RequestInterface $request, ResponseInterface $response)
+    {
+        $data = $request->getParams();
+
+        $check = Validator::notEmpty()->validate($data['collId']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['resTable']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['adrTable']);
+        $check = $check && Validator::intType()->notEmpty()->validate($data['resId']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['tmpDir']);
+        if (!$check) {
+            return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
+        }
+
+        $return = ProcessManageConvertController::convertAll($data);
+
+        if (empty($return) || !empty($return['errors'])) {
+            return $response->withStatus(500)->withJson(['errors' => '[ProcessConvertController create] ' . $return['errors']]);
+        }
+
+        return $response->withJson($return);
+    }
+
+    /**
+     * Ask for conversion in all mode
+     *
+     * @param string $collId collection
+     * @param string $resTable resource table
+     * @param string $adrTable adr table
+     * @param long $resId res_id
+     * @param string $tmpDir path to tmp
+     * @throws Exception Check des valeurs d'entrées
+     * @return array $returnArray the result
+     */
+    public function convertAll(array $args=[])
+    {
+        $timestart = microtime(true);
+        // prerequisites
+        $returnArray = array();
+        if (empty($args['collId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'collId empty for manage convert',
+            );
+            return $returnArray;
+        } else {
+            $collId = $args['collId'];
+        }
+        if (empty($args['resTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resTable empty for manage convert',
+            );
+            return $returnArray;
+        } else {
+            $resTable = $args['resTable'];
+        }
+        if (empty($args['adrTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'adrTable empty for manage convert',
+            );
+            return $returnArray;
+        } else {
+            $adrTable = $args['adrTable'];
+        }
+        if (empty($args['resId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resId empty for manage convert',
+            );
+            return $returnArray;
+        } else {
+            $resId = $args['resId'];
+        }
+        
+
+        if (!isset($args['tmpDir']) || $args['tmpDir'] == '') {
+            $tmpDir = $_SESSION['config']['tmppath'];
+        } else {
+            $tmpDir = $args['tmpDir'];
+        }
+
+        $path_to_lucene = '';
+        if (isset($args['path_to_lucene']) && !empty($args['path_to_lucene'])){
+            $path_to_lucene = $args['path_to_lucene'];
+        }
+
+        $params = array(
+            'collId'         => $collId, 
+            'resTable'       => $resTable, 
+            'adrTable'       => $adrTable, 
+            'resId'          => $resId,
+            'tmpDir'         => $tmpDir,
+            'path_to_lucene' => $path_to_lucene
+        );
+
+        //CONV
+        $ProcessConvertService = new ProcessConvertController();
+        $resultOfConversion = $ProcessConvertService->convert($params);
+        
+        if ($resultOfConversion['status'] <> '0') {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'CONV:' . $resultOfConversion['error'],
+            );
+            return $returnArray;
+        }
+
+        //TNL
+        $ProcessConvertService = new ProcessThumbnailsController();
+        $resultOfConversion = $ProcessConvertService->thumbnails($params);
+        if ($resultOfConversion['status'] <> '0') {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'TNL:' . $resultOfConversion['error'],
+            );
+            return $returnArray;
+        }
+
+        //FULLTEXT
+        if ($args['createZendIndex']) {
+            $params = array(
+                'collId'         => $collId, 
+                'resTable'       => $resTable, 
+                'adrTable'       => $adrTable, 
+                'resId'          => $resId,
+                'tmpDir'         => $tmpDir,
+                'path_to_lucene' => $path_to_lucene,
+                'createZendIndex' => true
+            );
+        } else {
+            $params = array(
+                'collId'         => $collId, 
+                'resTable'       => $resTable, 
+                'adrTable'       => $adrTable, 
+                'resId'          => $resId,
+                'tmpDir'         => $tmpDir,
+                'path_to_lucene' => $path_to_lucene
+            );
+        }
+        $ProcessConvertService = new ProcessFulltextController();
+        $resultOfConversion = $ProcessConvertService->fulltext($params);
+        if ($resultOfConversion['status'] <> '0') {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'TXT:' . $resultOfConversion['error'],
+            );
+            LogsController::executionTimeLog(
+                $timestart, 
+                '', 
+                'debug', 
+                '[TIMER] Convert_ManageConvertAbstract_Service::convertAll aucun contenu a indexer dans fulltext'
+            );
+            return $returnArray;
+        }
+        
+        $returnArray = array(
+            'status' => '0',
+            'value' => '',
+            'error' => '',
+        );
+        LogsController::executionTimeLog(
+            $timestart, 
+            '', 
+            'debug', 
+            '[TIMER] Convert_ManageConvertAbstract_Service::convertAll'
+        );
+
+        return $returnArray;
+    }
+}
\ No newline at end of file
diff --git a/modules/convert/Controllers/ProcessThumbnailsController.php b/modules/convert/Controllers/ProcessThumbnailsController.php
new file mode 100644
index 0000000000000000000000000000000000000000..c5c9b23b43e183b6c9360fc497169f49eeb6308e
--- /dev/null
+++ b/modules/convert/Controllers/ProcessThumbnailsController.php
@@ -0,0 +1,339 @@
+<?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 process thumbnails class
+*
+* <ul>
+* <li>Services to process the thumbnails of resources</li>
+* </ul>
+*
+* @file
+* @author Laurent Giovannoni <dev@maarch.org>
+* @date $date$
+* @version $Revision$
+* @ingroup convert
+*/
+
+namespace Convert\Controllers;
+
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+use Respect\Validation\Validator;
+use Convert\Models\ProcessThumbnailsModel;
+use Core\Models\CoreConfigModel;
+use Core\Models\DocserverModel;
+use Core\Models\ResDocserverModel;
+use Core\Models\ResModel;
+use Core\Controllers\LogsController;
+use Core\Controllers\StoreController;
+
+class ProcessThumbnailsController
+{
+    protected $tnlExecutable;
+
+    public function __construct($tnlExecutable = 'convert')
+    {
+        $this->tnlExecutable = $tnlExecutable;
+    }
+
+    public function create(RequestInterface $request, ResponseInterface $response)
+    {
+        $data = $request->getParams();
+
+        $check = Validator::notEmpty()->validate($data['collId']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['resTable']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['adrTable']);
+        $check = $check && Validator::intType()->notEmpty()->validate($data['resId']);
+        $check = $check && Validator::stringType()->notEmpty()->validate($data['tmpDir']);
+        if (!$check) {
+            return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
+        }
+
+        $return = ProcessThumbnailsController::thumbnails($data);
+
+        if (empty($return) || !empty($return['errors'])) {
+            return $response->withStatus(500)->withJson(['errors' => '[ProcessThumbnailsController create] ' . $return['errors']]);
+        }
+
+        return $response->withJson($return);
+    }
+
+    /**
+     * Ask for thumbnails
+     *
+     * @param string $collId collection
+     * @param string $resTable resource table
+     * @param string $adrTable adr table
+     * @param long $resId res_id
+     * @param string $tmpDir path to tmp
+     * @param array $tgtfmt array of target format
+     * @return array $returnArray the result
+     */
+    public function thumbnails(array $args=[])
+    {
+        $timestart = microtime(true);
+        $returnArray = array();
+        if (empty($args['collId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'collId empty for thumbnails',
+            );
+            return $returnArray;
+        } else {
+            $collId = $args['collId'];
+        }
+        if (empty($args['resTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resTable empty for thumbnails',
+            );
+            return $returnArray;
+        } else {
+            $resTable = $args['resTable'];
+        }
+        if (empty($args['adrTable'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'adrTable empty for thumbnails',
+            );
+            return $returnArray;
+        } else {
+            $adrTable = $args['adrTable'];
+        }
+        if (empty($args['resId'])) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'resId empty for thumbnails',
+            );
+            return $returnArray;
+        } else {
+            $resId = $args['resId'];
+        }
+
+        if (!isset($args['tmpDir']) || $args['tmpDir'] == '') {
+            $tmpDir = $_SESSION['config']['tmppath'];
+        } else {
+            $tmpDir = $args['tmpDir'];
+        }
+
+        $res = ResModel::getById(['resId' => $resId, 'resTable' => $args['resTable']]);
+
+        if ($res['res_id'] <> '') {
+            $adrType = 'CONV';
+            if (
+                strtoupper($res['format']) == 'HTML' ||
+                strtoupper($res['format']) == 'MAARCH'
+            ) {
+                $adrType = 'DOC';
+            }
+            $resourcePath = ResDocserverModel::getSourceResourcePath(
+                [
+                    'resTable' => $resTable, 
+                    'adrTable' => $adrTable, 
+                    'resId'    => $res['res_id'],
+                    'adrType'  => $adrType
+                ]
+            );
+        }
+        if (!file_exists($resourcePath)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'file not already converted in pdf for thumbnails. path :' 
+                    . $resourcePath . ", adrType : CONV, adr_table : " . $adrTable,
+            );
+            ProcessThumbnailsModel::manageErrorOnDb(
+                ['resTable' => $resTable, 'resId' => $resId, 'result' => '-1']
+            );
+            return $returnArray;
+        }
+
+        //copy the resource on tmp directory
+        $fileNameOnTmp = $tmpDir . rand() . rand();
+        if (!copy($resourcePath, $fileNameOnTmp)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'copy on tmp failed for thumbnails. Copy ' . $resourcePath . ' to ' . $fileNameOnTmp,
+            );
+            ProcessThumbnailsModel::manageErrorOnDb(
+                ['resTable' => $resTable, 'resId' => $resId, 'result' => '-1']
+            );
+            return $returnArray;
+        }
+
+        //now do the thumbnails !
+        $resultOfConversion = $this->launchThumbnails(
+            $fileNameOnTmp, 
+            $tmpDir,
+            pathinfo($resourcePath, PATHINFO_EXTENSION)
+        );
+
+
+        if ($resultOfConversion['status'] <> '0') {
+            ProcessThumbnailsModel::manageErrorOnDb(
+                ['resTable' => $resTable, 'resId' => $resId, 'result' => '-1']
+            );
+            LogsController::executionTimeLog(
+                $timestart, 
+                '', 
+                'debug', 
+                '[TIMER] Convert_ProcessThumbnailsAbstract_Service::thumbnails aucunContenuAIndexer'
+            );
+            return $resultOfConversion;
+        }
+
+        //copy the result on docserver
+        // LogsController::info(['message'=>'avant cp ds', 'code'=>1112, ]);
+        $storeResult = StoreController::storeResourceOnDocServer([
+            'collId'    => $collId,
+            'fileInfos' => [
+                'tmpDir'        => CoreConfigModel::getTmpPath(),
+                'size'          => filesize($fileNameOnTmp),
+                'format'        => 'PNG',
+                'tmpFileName'   => pathinfo($fileNameOnTmp, PATHINFO_FILENAME) . '.png',
+            ],
+            'docserverTypeId'   => 'TNL'
+        ]);
+
+        if (empty($storeResult)) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => 'Ds of collection and ds type not found for thumbnails:' 
+                    . $collId . ' THUMBNAILS',
+            );
+            ProcessThumbnailsModel::manageErrorOnDb(
+                ['resTable' => $resTable, 'resId' => $resId, 'result' => '-1']
+            );
+            return $returnArray;
+        }
+
+        $targetDs = DocserverModel::getById(['id' => $storeResult['docserver_id']]);
+
+        // LogsController::info(['message'=>'avant update', 'code'=>19, ]);
+        //update the Database
+        $resultOfUpDb = ProcessThumbnailsModel::updateDatabase(
+            [
+                'collId'     => $collId,
+                'resTable'   => $resTable, 
+                'adrTable'   => $adrTable, 
+                'resId'      => $resId,
+                'docserver'  => $targetDs,
+                'path'       => $storeResult['destination_dir'],
+                'fileName'   => $storeResult['file_destination_name']
+            ]
+        );
+
+        if ($resultOfUpDb['status'] <> '0') {
+            ProcessThumbnailsModel::manageErrorOnDb(
+                ['resTable' => $resTable, 'resId' => $resId, 'result' => '-1']
+            );
+            return $resultOfUpDb;
+        }
+
+        unlink($fileNameOnTmp);
+        unlink($fileNameOnTmp . '.png');
+
+        $returnArray = array(
+            'status' => '0',
+            'value' => '',
+            'error' => '',
+        );
+        LogsController::executionTimeLog(
+            $timestart, 
+            '', 
+            'debug', 
+            '[TIMER] Convert_ProcessThumbnailsAbstract_Service::thumbnails'
+        );
+        return $returnArray;
+    }
+
+    /**
+     * Launch the thumbnails process
+     *
+     * @param string $srcfile source file
+     * @param string $tgtdir target dir
+     * @param string $srcfmt source format
+     * @return array $returnArray the result
+     */
+    private function launchThumbnails(
+        $srcfile, 
+        $tgtdir=false, 
+        $srcfmt
+    ) {
+        $timestart = microtime(true);
+        if (!$tgtdir) {
+            $tgtdir = dirname($srcfile);
+        }
+
+        $output = array();
+        $return = null;
+        $this->errors = array();
+
+        //wkhtmltoimage must be installed with compiled sources
+        if (strtoupper($srcfmt) == 'MAARCH' || strtoupper($srcfmt) == 'HTML') {
+            copy($srcfile, str_ireplace('.maarch', '.', $srcfile) . '.html');
+            if (file_exists('/usr/bin/mywkhtmltoimage')) {
+                $command = "mywkhtmltoimage  --width 164 --height 105 --quality 100 --zoom 0.2 " 
+                    . escapeshellarg(str_ireplace('.maarch', '.', $srcfile) . '.html') . " " 
+                    . escapeshellarg($tgtdir . basename(str_ireplace('.maarch', '.', $srcfile)) . '.png');
+            } else {
+                $envVar = "export DISPLAY=FRPAROEMINT:0.0 ; ";
+                $command = $envVar . "wkhtmltoimage --width 164 --height 105 --quality 100 --zoom 0.2 " 
+                    . escapeshellarg(str_ireplace('.maarch', '.', $srcfile) . '.html') . " " 
+                    . escapeshellarg($tgtdir . basename(str_ireplace('.maarch', '.', $srcfile)) . '.png');
+            }
+        } else {
+            $command = "convert -thumbnail 200x300 -background white -alpha remove " 
+                . escapeshellarg($srcfile) . "[0] "
+                . escapeshellarg($tgtdir . basename($srcfile) . '.png');
+        }
+        //echo $command . PHP_EOL;exit;
+        $timestart_command = microtime(true);
+        exec($command, $output, $return);
+        LogsController::debug(['message'=>'[TIMER] Commande : ' . $command]);
+        LogsController::executionTimeLog($timestart_command, '', 'debug', '[TIMER] Convert_ProcessThumbnailsAbstract_Service::launchThumbnails__exec');
+
+        if ($return === 0) {
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+        } else {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => $return . $output,
+            );
+        }
+        if (strtoupper($srcfmt) == 'MAARCH' || strtoupper($srcfmt) == 'HTML') {
+            $returnArray = array();
+            unlink(str_ireplace('.maarch', '.', $srcfile) . '.html');
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+        }
+        LogsController::executionTimeLog(
+            $timestart, 
+            '', 
+            'debug', 
+            '[TIMER] Convert_ProcessThumbnailsAbstract_Service::launchThumbnails
+        ');
+        return $returnArray;
+    }
+}
diff --git a/modules/convert/Models/ProcessThumbnailsModel.php b/modules/convert/Models/ProcessThumbnailsModel.php
new file mode 100644
index 0000000000000000000000000000000000000000..c334b9fbccea69251c82b77eeaf7825d5797cd18
--- /dev/null
+++ b/modules/convert/Models/ProcessThumbnailsModel.php
@@ -0,0 +1,21 @@
+<?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 Process Thumbnails Model
+* @author dev@maarch.org
+* @ingroup convert
+*/
+
+namespace Convert\Models;
+
+class ProcessThumbnailsModel extends ProcessThumbnailsModelAbstract
+{
+    // Do your stuff in this class
+}
diff --git a/modules/convert/Models/ProcessThumbnailsModelAbstract.php b/modules/convert/Models/ProcessThumbnailsModelAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..f1819d9862beba630d35ef8448c94875381cac03
--- /dev/null
+++ b/modules/convert/Models/ProcessThumbnailsModelAbstract.php
@@ -0,0 +1,247 @@
+<?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 ProcessThumbnails Model
+* @author dev@maarch.org
+* @ingroup convert
+*/
+
+namespace Convert\Models;
+
+use Core\Models\DatabaseModel;
+use Core\Models\ValidatorModel;
+use Core\Controllers\HistoryController;
+
+class ProcessThumbnailsModelAbstract
+{
+    /**
+     * Updating the database with the location information of the document on the
+     * new docserver
+     * @param string $collId collection
+     * @param string $resTable res table
+     * @param string $adrTable adr table
+     * @param bigint $resId Id of the resource to process
+     * @param docserver $docserver docserver object
+     * @param string $path location of the resource on the docserver
+     * @param string $fileName file name of the resource on the docserver
+     * @param complex $zendIndex zend index object
+     * @return array $returnArray the result
+     */
+    public static function updateDatabase(array $aArgs = [])
+    {
+        try {
+            ValidatorModel::notEmpty($aArgs, ['collId']);
+            ValidatorModel::notEmpty($aArgs, ['resTable']);
+            ValidatorModel::notEmpty($aArgs, ['adrTable']);
+            ValidatorModel::intVal($aArgs, ['resId']);
+            ValidatorModel::notEmpty($aArgs, ['docserver']);
+            ValidatorModel::notEmpty($aArgs, ['path']);
+            ValidatorModel::notEmpty($aArgs, ['fileName']);
+
+            $aArgs['docserver']['path_template'] = str_replace(
+                DIRECTORY_SEPARATOR, 
+                '#', 
+                $aArgs['docserver']['path_template']
+            );
+            $aArgs['path'] = str_replace(
+                $aArgs['docserver']['path_template'], 
+                '', 
+                $aArgs['path']
+            );
+
+            DatabaseModel::update([
+                'table'     => 'convert_stack',
+                'set'       => [
+                    'status'    => 'P'
+                ],
+                'where'     => ['coll_id = ?', 'res_id = ?'],
+                'data'      => [$aArgs['collId'], $aArgs['resId']]
+            ]);
+
+            $returnAdr = DatabaseModel::select([
+                'select'    => ['*'],
+                'table'     => [$aArgs['adrTable']],
+                'where'     => ['res_id = ?'],
+                'data'      => [$aArgs['resId']],
+                'order'      => ['adr_priority'],
+            ]);
+
+            if (empty($returnAdr)) {
+                $returnRes = DatabaseModel::select([
+                    'select'    => ['docserver_id, path, filename, offset_doc, fingerprint'],
+                    'table'     => [$aArgs['resTable']],
+                    'where'     => ['res_id = ?'],
+                    'data'      => [$aArgs['resId']]
+                ]);
+                $returnRes = $returnRes[0];
+                // LogsController::info(['message'=>$returnRes, 'code'=>8, ]);
+                $resDocserverId = $returnRes['docserver_id'];
+                $resPath = $returnRes['path'];
+                $resFilename = $returnRes['filename'];
+                $resOffsetDoc = $returnRes['offset_doc'];
+                $fingerprintInit = $returnRes['fingerprint'];
+
+                $returnDs = DatabaseModel::select([
+                    'select'    => ['adr_priority_number'],
+                    'table'     => ['docservers'],
+                    'where'     => ['docserver_id = ?'],
+                    'data'      => [$resDocserverId]
+                ]);
+
+                DatabaseModel::insert([
+                    'table'         => $aArgs['adrTable'],
+                    'columnsValues' => [
+                        'res_id'        => $aArgs['resId'],
+                        'docserver_id'  => $resDocserverId,
+                        'path'          => $resPath,
+                        'filename'      => $resFilename,
+                        'offset_doc'    => $resOffsetDoc,
+                        'fingerprint'   => $fingerprintInit,
+                        'adr_priority'  => $returnDs[0]['adr_priority_number'],
+                    ]
+                ]);
+            }
+
+            $returnAdr = DatabaseModel::select([
+                'select'    => ['*'],
+                'table'     => [$aArgs['adrTable']],
+                'where'     => ['res_id = ?', 'adr_type= ?'],
+                'data'      => [$aArgs['resId'], 'TNL'],
+            ]);
+            
+            if (empty($returnAdr)) {
+                DatabaseModel::insert([
+                    'table'         => $aArgs['adrTable'],
+                    'columnsValues' => [
+                        'res_id'        => $aArgs['resId'],
+                        'docserver_id'  => $aArgs['docserver']['docserver_id'],
+                        'path'          => $aArgs['path'],
+                        'filename'      => $aArgs['fileName'],
+                        'offset_doc'    => $offsetDoc,
+                        'fingerprint'   => $fingerprint,
+                        'adr_priority'  => $aArgs['docserver']['adr_priority_number'],
+                        'adr_type'      => 'TNL',
+                    ]
+                ]);
+            } else {
+                DatabaseModel::update([
+                    'table'     => $aArgs['adrTable'],
+                    'set'       => [
+                        'docserver_id'  => $aArgs['docserver']['docserver_id'],
+                        'path'          => $aArgs['path'],
+                        'filename'      => $aArgs['fileName'],
+                        'offset_doc'    => $offsetDoc,
+                        'fingerprint'   => $fingerprint,
+                        'adr_priority'  => $aArgs['docserver']['adr_priority_number'],
+                    ],
+                    'where'     => ['res_id = ?', "adr_type = ?"],
+                    'data'      => [$aArgs['resId'], 'TNL']
+                ]);
+            }
+
+            HistoryController::add([
+                'tableName' => $aArgs['resTable'],
+                'recordId'  => (string) $aArgs['resId'],
+                'eventType' => 'ADD',
+                'info'      => 'process thumbnails done',
+                'moduleId'  => 'convert',
+                'eventId'   => 'thumbnails',
+            ]);
+
+            $queryCpt = DatabaseModel::select([
+                'select'    => ["tnl_attempts"],
+                'table'     => [$aArgs['resTable']],
+                'where'     => ['res_id = ?'],
+                'data'      => [$aArgs['resId']],
+            ]);
+
+            $cptThumbnails = $queryCpt[0]['tnl_attempts'] + 1;
+
+            DatabaseModel::update([
+                'table'     => $aArgs['resTable'],
+                'set'       => [
+                    'tnl_result'          => 1,
+                    'is_multi_docservers' => 'Y',
+                    'tnl_attempts'        => $cptThumbnails,
+                ],
+                'where'     => ['res_id = ?'],
+                'data'      => [$aArgs['resId']]
+            ]);
+
+            $returnArray = array(
+                'status' => '0',
+                'value' => '',
+                'error' => '',
+            );
+            
+            return $returnArray;
+        } catch (Exception $e) {
+            $returnArray = array(
+                'status' => '1',
+                'value' => '',
+                'error' => $e->getMessage(),
+            );
+
+            return $returnArray;
+        }
+    }
+
+    public static function getById(array $aArgs = [])
+    {
+        ValidatorModel::notEmpty($aArgs, ['resId']);
+        ValidatorModel::intVal($aArgs, ['resId']);
+
+        $aReturn = DatabaseModel::select([
+            'select'    => empty($aArgs['select']) ? ['*'] : $aArgs['select'],
+            'table'     => ['res_letterbox'],
+            'where'     => ['res_id = ?'],
+            'data'      => [$aArgs['resId']]
+        ]);
+
+        if (empty($aReturn[0])) {
+            return [];
+        }
+
+        return $aReturn[0];
+    }
+
+    /**
+     * Updating the database with the error code
+     * @param string $resTable res table
+     * @param bigint $resId Id of the resource to process
+     * @param string $result error code
+     * @return nothing
+     */
+    public static function manageErrorOnDb(array $aArgs = [])
+    {
+        $attemptsRecord = DatabaseModel::select([
+            'select'    => ['tnl_attempts'],
+            'table'     => [$aArgs['resTable']],
+            'where'     => ['res_id = ?'],
+            'data'      => [$aArgs['resId']],
+        ]);
+
+        if (empty($attemptsRecord)) {
+            $attempts = 0;
+        } else {
+            $attempts = $attemptsRecord[0]['tnl_attempts'] + 1;
+        }
+
+        DatabaseModel::update([
+            'table'     => $aArgs['resTable'],
+            'set'       => [
+                'tnl_result' => $aArgs['result'],
+                'tnl_attempts' => $attempts,
+            ],
+            'where'     => ['res_id = ?'],
+            'data'      => [$aArgs['resId']]
+        ]);
+    }
+}
diff --git a/modules/convert/Test/ProcessManageConvertTest.php b/modules/convert/Test/ProcessManageConvertTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..470e953f990a6b55362e5295a0b389e1f1a45bb3
--- /dev/null
+++ b/modules/convert/Test/ProcessManageConvertTest.php
@@ -0,0 +1,127 @@
+<?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.
+*
+*/
+
+namespace MaarchTest;
+use PHPUnit\Framework\TestCase;
+
+class ManageProcessConvertTest extends TestCase
+{
+    public function testmanageConvert ()
+    {
+        $action = new \Core\Controllers\ResController();
+
+        $environment = \Slim\Http\Environment::mock(
+            [
+                'REQUEST_METHOD' => 'POST',
+            ]
+        );
+
+        $path = $_SESSION['config']['tmppath'] . '/test/';
+
+        if (!is_dir($path)) {
+            mkdir($path);
+        }
+
+        $fileSource = 'test_source.txt';
+        
+        if (file_exists($path . $fileSource)) {
+            unlink($path . $fileSource);
+        }
+
+        $fp = fopen($path . $fileSource, 'a');
+        fwrite($fp, 'a unit test for PHP CONVERSION lorem ipsum...');
+        fclose($fp);
+
+        $fileContent = file_get_contents($path . $fileSource, FILE_BINARY);
+        $encodedFile = base64_encode($fileContent);
+        //echo $encodedFile . PHP_EOL;exit;
+        
+        $data = [];
+
+        array_push(
+            $data,
+            array(
+                'column' => 'subject',
+                'value' => 'UNIT TEST from slim',
+                'type' => 'string',
+            )
+        );
+
+        array_push(
+            $data,
+            array(
+                'column' => 'type_id',
+                'value' => 110,
+                'type' => 'integer',
+            )
+        );
+
+        array_push(
+            $data,
+            array(
+                'column' => 'custom_t1',
+                'value' => 'TEST',
+                'type' => 'string',
+            )
+        );
+
+        array_push(
+            $data,
+            array(
+                'column' => 'custom_t10',
+                'value' => 'lgi@maarch.org',
+                'type' => 'string',
+            )
+        );
+
+        $aArgs = [
+            'encodedFile'   => $encodedFile,
+            'data'          => $data,
+            'collId'        => 'letterbox_coll',
+            'table'         => 'res_letterbox',
+            'fileFormat'    => 'txt',
+            'status'        => 'new',
+        ];
+
+        $request = \Slim\Http\Request::createFromEnvironment($environment);
+        $response = new \Slim\Http\Response();
+        $fullRequest = \httpRequestCustom::addContentInBody($aArgs, $request);
+
+        $response = $action->create($fullRequest, $response);
+        $responseBody = json_decode((string)$response->getBody());
+        
+        $resId = $responseBody->resId;
+        
+        if (!defined("_RES_ID_TEST_CONVERT")) {
+            define("_RES_ID_TEST_CONVERT", $resId);
+        }
+
+        //real test
+        $request = \Slim\Http\Request::createFromEnvironment($environment);
+        $action = new \Convert\Controllers\ProcessManageConvertController();
+
+        $aArgs = [
+            'collId' => 'letterbox_coll', 
+            'resTable' => 'res_letterbox', 
+            'adrTable' => 'adr_letterbox', 
+            'resId' => _RES_ID_TEST_CONVERT, 
+            'tmpDir' => $_SESSION['config']['tmppath'],
+            'createZendIndex' => true
+        ];
+
+        $response = new \Slim\Http\Response();
+        $fullRequest = \httpRequestCustom::addContentInBody($aArgs, $request);
+
+        $response = $action->create($fullRequest, $response);
+        $responseBody = json_decode((string)$response->getBody());
+        $status = $responseBody->status;
+        
+        $this->assertEquals('0', $status);
+    }
+}
diff --git a/modules/convert/Test/ProcessThumbnailsTest.php b/modules/convert/Test/ProcessThumbnailsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..0007f083f24fe1ea3098d8e6830302e9ae54b2ce
--- /dev/null
+++ b/modules/convert/Test/ProcessThumbnailsTest.php
@@ -0,0 +1,52 @@
+<?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.
+*
+*/
+
+namespace MaarchTest;
+use PHPUnit\Framework\TestCase;
+
+class ProcessThumbnailsTest extends TestCase
+{
+
+    public function testthumbnails ()
+    {
+        
+        if (!defined("_RES_ID_TEST_CONVERT")) {
+            define("_RES_ID_TEST_CONVERT", 100);
+        }
+
+        $action = new \Convert\Controllers\ProcessThumbnailsController();
+
+        $environment = \Slim\Http\Environment::mock(
+            [
+                'REQUEST_METHOD' => 'POST',
+            ]
+        );
+
+        $request = \Slim\Http\Request::createFromEnvironment($environment);
+
+        $aArgs = [
+            'collId' => 'letterbox_coll', 
+            'resTable' => 'res_letterbox', 
+            'adrTable' => 'adr_letterbox', 
+            'resId' => _RES_ID_TEST_CONVERT,
+            'tmpDir' => $_SESSION['config']['tmppath']
+        ];
+
+        $response = new \Slim\Http\Response();
+        $fullRequest = \httpRequestCustom::addContentInBody($aArgs, $request);
+
+        $response = $action->create($fullRequest, $response);
+        //var_dump($response);
+        $responseBody = json_decode((string)$response->getBody());
+        //var_dump($responseBody);
+        $status = $responseBody->status;
+        
+        $this->assertEquals('0', $status);
+    }
+}