Merge branch 'module_training'

This commit is contained in:
Rodney Figaro 2017-03-23 17:21:38 +01:00
commit 686ea216aa
18 changed files with 1764 additions and 0 deletions

View File

@ -0,0 +1,36 @@
<?php
class AdminTrainingPharmacyController extends ModuleAdminController
{
public function __construct() {
$this->table = 'training_pharmacy';
$this->className = 'TrainingPharmacy';
$this->identifier = 'id_training_pharmacy';
$this->lang = FALSE;
$this->deleted = FALSE;
$this->bootstrap = TRUE;
$this->_defaultOrderBy = 'codeclient';
$this->toolbar_btn = array();
parent::__construct();
$this->actions = array();
$this->fields_list = array(
'id_training_pharmacy' => array(
'title' => 'ID',
'width' => 25
),
'codeclient' => array(
'title' => $this->module->l('Code client'),
'width' => 60,
),
);
}
public function renderView()
{
return $this->renderList();
}
}

View File

@ -0,0 +1,278 @@
<?php
ini_set('upload_max_filesize', '100M');
ini_set('post_max_size', '20M');
include_once(_PS_MODULE_DIR_.'training/models/TrainingBilan.php');
class AdminTrainingController extends ModuleAdminController
{
private $path_files = '';
private $path_output_files = '';
function __construct()
{
parent::__construct();
$this->path_files = __DIR__.'/../../upload/';
$this->url_upload_path = '/modules/training/upload/';
$this->path_output_files = __DIR__.'/../../output/';
$this->url_output_path = '/modules/training/output/';
}
function display()
{
$this->setTemplate('home.tpl');
$this->context->smarty->assign(array(
'link_training_modules' => Context::getContext()->link->getAdminLink('AdminTrainingModules', true),
'link_self' => Context::getContext()->link->getAdminLink('AdminTraining', true),
));
parent::display();
}
function initContent()
{
$this->context->smarty->assign('url_upload_path', $this->url_upload_path);
$this->context->smarty->assign('url_output_path', $this->url_output_path);
$this->context->smarty->assign('used_module_file', Configuration::get('TRAINING_USED_MODULE_FILE'));
$this->context->smarty->assign('used_pharmacy_file', Configuration::get('TRAINING_USED_PHARMACY_FILE'));
$this->context->smarty->assign('used_results_file', Configuration::get('TRAINING_USED_RESULT_FILE'));
$this->context->smarty->assign('used_fixedcodes_file', Configuration::get('TRAINING_FIXEDCODES_FILE'));
$this->context->smarty->assign('bilan_file', Configuration::get('TRAINING_BILAN_FILE'));
$this->context->smarty->assign('corrected_results_file', Configuration::get('TRAINING_CORRECTED_RESULT_FILE'));
$this->context->smarty->assign('corrected_codes_file', Configuration::get('TRAINING_CORRECTED_CODES_FILE'));
if (Tools::isSubmit('submitFileModules')) {
$this->submitFileModules();
}
elseif (Tools::isSubmit('submitFilePharmacies')) {
$this->submitFilePharmacies();
}
elseif (Tools::isSubmit('submitFileResults')) {
$this->submitFileResults();
}
elseif (Tools::isSubmit('generateBilan')) {
$this->generateBilan();
}
elseif (Tools::isSubmit('submitFileFixedCodes')) {
$this->submitFileFixedCodes();
}
}
function submitFileModules()
{
$file = $this->moveUploadedCsvFile('module_filename');
if ($file!==null) {
$ok = TrainingModule::importFromCsvFile($file->path);
if ($ok) {
Configuration::updateValue('TRAINING_USED_MODULE_FILE', $file->name);
$this->context->smarty->assign('used_module_file', $file->name);
$this->confirmations[] = $this->l(sprintf('Importation des modules et catégories réussie.'));
}
else {
$this->errors[] = $this->l('Echec de l\'importation des modules et catégories. Il est possible de les éditer manuellement.');
}
}
}
function submitFilePharmacies()
{
$file = $this->moveUploadedCsvFile('pharmacy_filename');
if ($file!==null) {
$ok = TrainingPharmacy::importFromCsvFile($file->path);
if ($ok) {
Configuration::updateValue('TRAINING_USED_PHARMACY_FILE', $file->name);
$this->context->smarty->assign('used_pharmacy_file', $file->name);
$this->confirmations[] = $this->l(sprintf('Importation des pharmacies réussie.'));
}
else {
$this->errors[] = $this->l(sprintf('Echec de l\'importation des pharmacies.'));
}
}
}
function submitFileResults()
{
$file = $this->moveUploadedCsvFile('results_filename');
if ($file!==null) {
Configuration::updateValue('TRAINING_USED_RESULT_FILE', $file->name);
$this->context->smarty->assign('used_results_file', $file->name);
}
}
function submitFileFixedCodes()
{
$file = $this->moveUploadedCsvFile('fixed_codes_filename');
if ($file!==null) {
$ok = TrainingFixedCodeClient::importFromCsvFile($file->path);
if ($ok) {
Configuration::updateValue('TRAINING_FIXEDCODES_FILE', $file->name);
$this->context->smarty->assign('used_fixedcodes_file', $file->name);
$this->confirmations[] = $this->l(sprintf('Importation des codes clients corrigés réussie.'));
}
else {
$this->errors[] = $this->l(sprintf('Echec de l\'importation des codes clients corrigés.'));
}
}
}
function generateBilan()
{
// check all required data are defined
if (!TrainingPharmacy::hasAnyRow()) {
$this->errors[] = $this->l(sprintf('Merci d\'importer un fichier csv pharmacies.'));
}
if (!TrainingModule::hasAnyRow()) {
$this->errors[] = $this->l(sprintf('Merci d\'ajouter les modules/catégories.'));
}
$result_filename = Configuration::get('TRAINING_USED_RESULT_FILE');
if (empty($result_filename)) {
$this->errors[] = $this->l(sprintf('Merci d\'importer un fichier de résultats.'));
}
if (0 == count($this->errors)) {
$d = new DateTime();
$corrected_results_file = 'RESULTAT_CORRIGE_'.$d->format('Y-m-d_His').'.csv';
$corrected_codes_file = 'CODES_CORRIGE_'.$d->format('Y-m-d_His').'.csv';
$bilan_file = 'BILAN_'.$d->format('Y-m-d_His').'.csv';
$ok = TrainingBilan::generate(
$this->path_files.$result_filename,
$this->path_output_files.$corrected_results_file,
$this->path_output_files.$bilan_file,
$this->path_output_files.$corrected_codes_file
);
if ($ok) {
Configuration::updateValue('TRAINING_BILAN_FILE', $bilan_file);
Configuration::updateValue('TRAINING_CORRECTED_RESULT_FILE', $corrected_results_file);
Configuration::updateValue('TRAINING_CORRECTED_CODES_FILE', $corrected_codes_file);
$this->context->smarty->assign('bilan_file', Configuration::get('TRAINING_BILAN_FILE'));
$this->context->smarty->assign('corrected_results_file', Configuration::get('TRAINING_CORRECTED_RESULT_FILE'));
$this->context->smarty->assign('corrected_codes_file', Configuration::get('TRAINING_CORRECTED_CODES_FILE'));
$this->confirmations[] = 'Génération des fichiers "bilan", "résultats corrigés" et "codes corrigés" réussie :
<br />
<br />
<ul>
<li>- Télécharger : <a href="'.$this->url_output_path.$bilan_file.'" target="_blank">'.$bilan_file.'</a></li>
<li>- Télécharger : <a href="'.$this->url_output_path.$corrected_results_file.'" target="_blank">'.$corrected_results_file.'</a></li>
<li>- Télécharger : <a href="'.$this->url_output_path.$corrected_codes_file.'" target="_blank">'.$corrected_codes_file.'</a></li>
</ul>
<br />
Retrouvez les liens vers ces fichiers depuis l\'encadré BILAN / RESULTAT CORRIG&Eacute;.
';
}
else {
$this->errors[] = $this->l(sprintf('Echec du traitement du fichier résultat.'));
}
}
}
private function moveUploadedCsvFile($input_name)
{
if (!isset($_FILES[$input_name])) {
return null;
}
$f = (object)$_FILES[$input_name];
$f->name = basename($f->name);
$f->path = $this->path_files.$f->name;
$max_file_size = $this->getFileSizeMax();
if ($f->error === UPLOAD_ERR_OK) {
if ($f->size > $max_file_size) {
$f->error = UPLOAD_ERR_FORM_SIZE;
}
}
if ($f->error !== UPLOAD_ERR_OK) {
$this->errors[] = $this->codeToMessage($f, $max_file_size);
return null;
}
// ensure it is a CSV
$path_parts = pathinfo($f->path);
if (strtolower($path_parts['extension'])!='csv') {
$this->errors[] = $this->l('Seul un fichier CSV est accepté (extension ".csv").');
return null;
}
$success = move_uploaded_file($f->tmp_name,$f->path);
if (!$success) {
$this->errors[] = $this->l(sprintf('Echec lors l\'envoi du fichier %s.', $f->name));
return null;
}
$this->confirmations[] = $this->l(sprintf('Envoi du fichier "%s" réussi.', $f->name));
return $f;
}
private function getFileSizeMax()
{
$max_ini_file_size = ini_get('upload_max_filesize');
if (preg_match('/G/i', $max_ini_file_size)) {
$max_ini_file_size *= 1000000000;
}
if (preg_match('/M/i', $max_ini_file_size)) {
$max_ini_file_size *= 1000000;
}
if (preg_match('/K/i', $max_ini_file_size)) {
$max_ini_file_size *= 1000;
}
$max_file_size = Tools::getValue('MAX_FILE_SIZE', $max_ini_file_size);
if ($max_file_size > $max_ini_file_size) {
$max_file_size = $max_ini_file_size;
}
return $max_file_size;
}
private function codeToMessage($file, $max_file_size)
{
switch ($file->error) {
case UPLOAD_ERR_INI_SIZE:
$message = $this->l(sprintf('Erreur - Le fichier dépasse la taille maximale autorisée par le serveur : %d octets.', $max_file_size));
break;
case UPLOAD_ERR_FORM_SIZE:
$message = $this->l(sprintf('Erreur - Le fichier dépasse la taille maximale autorisée : %d octets.', $max_file_size));
break;
case UPLOAD_ERR_PARTIAL:
$message = $this->l('Erreur - Le fichier a été envoyé partiellement.');
break;
case UPLOAD_ERR_NO_FILE:
$message = $this->l('Erreur - Merci de sélectionner un fichier.');
break;
case UPLOAD_ERR_NO_TMP_DIR:
$message = $this->l("Erreur serveur - répertoire temporaire manquant.");
break;
case UPLOAD_ERR_CANT_WRITE:
$message = $this->l("Erreur serveur - répertoire non autorisé en écriture.");
break;
case UPLOAD_ERR_EXTENSION:
$message = $this->l("Erreur - Type de fichier refusé.");
break;
default:
$message = $this->l("Erreur serveur - Erreur inconnue.");
break;
}
return $message;
}
}

View File

@ -0,0 +1,69 @@
<?php
class AdminTrainingFixedCodeClientController extends ModuleAdminController
{
public function __construct() {
$this->table = 'training_fixedcodeclient';
$this->className = 'TrainingFixedCodeClient';
$this->identifier = 'id_training_fixedcodeclient';
$this->lang = FALSE;
$this->deleted = FALSE;
$this->bootstrap = TRUE;
$this->_defaultOrderBy = 'codeclient_from_results';
parent::__construct();
$this->actions = array('edit');
$this->fields_list = array(
'id_training_fixedcodeclient' => array(
'title' => 'ID',
'width' => 40
),
'codeclient_from_results' => array(
'title' => $this->module->l('Code client trouvé dans les résultats'),
'width' => 200,
),
'codeclient_fixed' => array(
'title' => $this->module->l('Code client corrigé'),
'width' => 150,
),
);
}
public function renderView()
{
return $this->renderList();
}
public function renderForm()
{
$this->fields_form = array(
'submit' => array(
'name' => 'submitTrainingFixedCodeClient',
'title' => $this->l('Save'),
),
'input' => array(
array(
'type' => 'text',
'label' => $this->l('Code client trouvé dans les résultats'),
'name' => 'codeclient_from_results',
'required' => TRUE,
'lang' => FALSE,
'size' => 128
),
array(
'type' => 'text',
'label' => $this->l('Code client corrigé'),
'name' => 'codeclient_fixed',
'required' => TRUE,
'lang' => FALSE,
'size' => 128
),
)
);
return parent::renderForm();
}
}

View File

@ -0,0 +1,69 @@
<?php
class AdminTrainingModulesController extends ModuleAdminController
{
public function __construct() {
$this->table = 'training_module';
$this->className = 'TrainingModule';
$this->identifier = 'id_training_module';
$this->lang = FALSE;
$this->deleted = FALSE;
$this->bootstrap = TRUE;
$this->_defaultOrderBy = 'category_name';
parent::__construct();
$this->actions = array('edit', 'delete');
$this->fields_list = array(
'id_training_module' => array(
'title' => 'ID',
'width' => 40
),
'module_name' => array(
'title' => $this->module->l('Module'),
'width' => 150,
),
'category_name' => array(
'title' => $this->module->l('Catégorie'),
'width' => 150,
),
);
}
public function renderView()
{
return $this->renderList();
}
public function renderForm()
{
$this->fields_form = array(
'submit' => array(
'name' => 'submitTrainingModule',
'title' => $this->l('Save'),
),
'input' => array(
array(
'type' => 'text',
'label' => $this->l('Libellé module'),
'name' => 'module_name',
'required' => TRUE,
'lang' => FALSE,
'size' => 128
),
array(
'type' => 'text',
'label' => $this->l('Libellé catégorie'),
'name' => 'category_name',
'required' => TRUE,
'lang' => FALSE,
'size' => 128
),
)
);
return parent::renderForm();
}
}

View File

@ -0,0 +1,35 @@
<?php
class AdminTrainingPharmacyController extends ModuleAdminController
{
public function __construct() {
$this->table = 'training_pharmacy';
$this->className = 'TrainingPharmacy';
$this->identifier = 'id_training_pharmacy';
$this->lang = FALSE;
$this->deleted = FALSE;
$this->bootstrap = TRUE;
$this->_defaultOrderBy = 'codeclient';
parent::__construct();
$this->actions = array();
$this->fields_list = array(
'id_training_pharmacy' => array(
'title' => 'ID',
'width' => 40
),
'codeclient' => array(
'title' => $this->module->l('Code client'),
'width' => 150,
),
);
}
public function renderView()
{
return $this->renderList();
}
}

View File

@ -0,0 +1,35 @@
<?php
/*
* 2007-2013 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2013 PrestaShop SA
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;

BIN
modules/training/logo.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

BIN
modules/training/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,46 @@
<?php
class ArrayExtended implements IteratorAggregate, ArrayAccess
{
private $collection;
function __construct(array $ar = array())
{
$this->collection = $ar;
}
function toArray()
{
return $this->collection;
}
function getIterator()
{
return new ArrayIterator($this->collection);
}
function offsetExists($offset)
{
return isset($this->collection[$offset]);
}
function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->collection[] = $value;
}
elseif (!empty($offset)) {
$this->collection[$offset] = $value;
}
}
function offsetUnset($offset)
{
unset($this->collection[$offset]);
}
function offsetGet($offset)
{
return isset($this->collection[$offset])?$this->collection[$offset]:null;
}
}

View File

@ -0,0 +1,140 @@
<?php
require_once(__DIR__.'/ArrayExtended.php');
class CSVReader
{
private $file_path = '';
private $params = array('enable_skip_line' => false, 'auto_detect'=>true, 'separator' => ',', 'enclosure' => '"', 'expected_header' => array());
private $handlers = array('start' => null, 'error' => null);
private $current_num_line = 0;
private $expected_cols_index = array();
function __construct($file_path)
{
$this->file_path = $file_path;
$this->handlers = array(
'start' => function() {},
'error' => function($failed_line_number) {},
'readline' => function(ArrayExtended $cols) { return true; }
);
}
function setExpectedHeader(array $expected_header)
{
$this->params['expected_header'] = $expected_header;
return $this;
}
function enableSkipHeader()
{
$this->params['enable_skip_line'] = true;
return $this;
}
// func : function()
function setOnStart(callable $func)
{
$this->handlers['start'] = $func;
return $this;
}
// func : function(ArrayExtended $columns)
function setOnEachLine(callable $func)
{
$this->handlers['readline'] = $func;
return $this;
}
// func : function(int failed_line_number)
function setOnError(callable $func)
{
$this->handlers['error'] = $func;
return $this;
}
function readLines()
{
$ok = false;
$this->current_num_line = 0;
if ($this->params['auto_detect']) {
$this->autoDetect($this->file_path);
}
$f = fopen($this->file_path, 'r');
if ($f) {
call_user_func($this->handlers['start']);
$ok = true;
if ($this->params['enable_skip_line'] || count($this->params['expected_header'])>0) {
$ok = $this->checkHeader(fgetcsv($f, 0, $this->params['separator'], $this->params['enclosure']));
}
while ($ok && ($cols = fgetcsv($f, 0, $this->params['separator'], $this->params['enclosure']))) {
$real_cols = array();
foreach($this->expected_cols_index as $real_index => $index) {
$real_cols[$index] = $cols[$real_index];
}
$ok = call_user_func($this->handlers['readline'], new ArrayExtended($real_cols));
$this->current_num_line++;
}
fclose($f);
}
if (!$ok) {
call_user_func($this->handlers['error'], $this->current_num_line);
}
return $ok;
}
private function checkHeader(array $cols)
{
$ok = true;
foreach($this->params['expected_header'] as $expected_col => $expected_pos) {
$found = false;
foreach($cols as $index => $col) {
if (strtolower($col) == strtolower($expected_col)) {
$this->expected_cols_index[$index] = $expected_pos;
$found = true;
break;
}
}
$ok = $ok && $found;
}
return $ok;
}
private function autoDetect($file_path)
{
if ($f = fopen($file_path, 'r')) {
$line = fgets($f);
if ($line[0] == '"') {
$line[0] = '';
$line = str_replace("\\\"", '', $line);
$line = str_replace("\"\"", '', $line);
$line = strstr($line, '"');
if (strlen($line)>1) {
$this->params['separator'] = $line[1];
}
}
else {
if (strpos($line, ';')!==false) {
$this->params['separator'] = ';';
}
elseif (strpos($line, ',')!==false) {
$this->params['separator'] = ',';
}
elseif (strpos($line, '|')!==false) {
$this->params['separator'] = '|';
}
}
fclose($f);
}
}
}

View File

@ -0,0 +1,107 @@
<?php
class CSVWriter
{
const SAVE = 1;
const OUTPUT_FOR_DOWNLOAD = 2;
private $file_path;
private $buffer;
private $header = null;
private $footer = null;
private $lines = array();
function __construct($file_path)
{
$this->file_path = $file_path;
}
function setHeader(array $line)
{
$this->header = $line;
return $this;
}
function addLine(array $line)
{
$this->lines[] = $line;
return $this;
}
function setFooter(array $line)
{
$this->footer = $line;
return $this;
}
function sortBy($index_column, $ascendant=true)
{
usort($this->lines,
function(array $a, array $b) use ($index_column, $ascendant) {
if ($a[$index_column] < $b[$index_column]) {
return $ascendant?-1:1;
}
else if ($a[$index_column] > $b[$index_column]) {
return $ascendant?1:-1;
}
else {
return 0;
}
});
return $this;
}
function save()
{
if (empty($this->buffer)) {
$this->flush();
}
$f = fopen($this->file_path, 'w');
if ($f) {
fwrite($f, $this->buffer);
fclose($f);
}
return $this;
}
function outputForDownload()
{
if (empty($this->buffer)) {
$this->flush();
}
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
header("Content-Type: text/csv");
header("Content-Disposition: attachment; filename=\"".basename($this->file_path)."\";" );
header("Content-Transfer-Encoding: binary");
exit($this->buffer);
}
private function flush()
{
$output = fopen('php://output', 'w');
ob_start();
if (is_array($this->header)) {
fwrite($output, implode(';', $this->header).PHP_EOL);
}
foreach($this->lines as $line) {
fwrite($output, implode(';', $line).PHP_EOL);
}
if (is_array($this->footer)) {
fwrite($output, implode(';', $this->footer).PHP_EOL);
}
$this->buffer = ob_get_clean();
return $this;
}
}

View File

@ -0,0 +1,216 @@
<?php
require_once __DIR__.'/CSVReader.php';
require_once __DIR__.'/CSVWriter.php';
require_once __DIR__.'/TrainingModule.php';
require_once __DIR__.'/TrainingPharmacy.php';
require_once __DIR__.'/TrainingFixedCodeClient.php';
class TrainingBilan
{
const TOTAL_MARGIN = 2;
const COL_MODULE_NAME = 1;
const COL_CODE_CLIENT = 2;
const COL_FIRSTNAME = 3;
const COL_LASTNAME = 4;
const COL_TEL = 5;
const COL_PHARMACY = 6;
const COL_CITY = 7;
const COL_ATTEMPT_DATE = 8;
const COL_STATUS = 9;
const COL_VALIDE = 11;
const OUTPUT_COLUMN_CODECLIENT = 0;
static private $bilan = array();
static private $pharmacies_notfound = array();
static private $modules = null;
static private $pharmacies = null;
static private $pharmacies_fixeds = null;
static private $results_corrected = array();
static function generate(
$result_file_path,
$output_corrected_result_file_path,
$output_bilan_file_path,
$output_corrected_codes_file_path
)
{
// Define the expected header of the result file
$expectedHeader = array(
'Module' => self::COL_MODULE_NAME,
'Code Client' => self::COL_CODE_CLIENT,
'Prenom' => self::COL_FIRSTNAME,
'NOM' => self::COL_LASTNAME,
'Telephone' => self::COL_TEL,
'Nom pharmacie' => self::COL_PHARMACY,
'Ville' => self::COL_CITY,
'Date' => self::COL_ATTEMPT_DATE,
'Statut' => self::COL_STATUS,
);
self::$bilan = array();
self::$pharmacies_notfound = array();
self::$modules = TrainingModule::loadAll();
self::$pharmacies = TrainingPharmacy::loadAll();
self::$pharmacies_fixeds = TrainingFixedCodeClient::loadOnlyFixed();
// Read the imported result file
$reader = new CSVReader($result_file_path);
$ok = $reader->enableSkipHeader()
->setExpectedHeader($expectedHeader)
->setOnEachLine("TrainingBilan::computeLineResult")
->readLines();
if (!$ok) {
return false;
}
// Add all (maybe new) incorrect codes
TrainingFixedCodeClient::addIfNotExist(self::$pharmacies_notfound);
// Export the correct result file in the same format (with 1 additionnal column)
$newHeader = $expectedHeader + array('Validé' => self::COL_VALIDE);
$csv_output = new CSVWriter($output_corrected_result_file_path);
self::exportCorrectedResults($newHeader, $csv_output);
$csv_output->save();
// Export the corrected codes file in the same format of the codes clients file imported in class TrainingFixedCodeClient
TrainingFixedCodeClient::exportIntoCsvFile($output_corrected_codes_file_path);
// Export the "bilan"
$csv_output = new CSVWriter($output_bilan_file_path);
self::exportResults($csv_output);
$csv_output->sortBy(self::OUTPUT_COLUMN_CODECLIENT);
$csv_output->save();
return true;
}
static function computeLineResult(ArrayExtended $cols)
{
$code_client = strtolower($cols[self::COL_CODE_CLIENT]);
$low_module_name = strtolower($cols[self::COL_MODULE_NAME]);
if (empty($code_client)) {
$code_client = TrainingFixedCodeClient::CODE_EMPTY;
}
// for the current code found in result file,
// retrive the corrected one if any
// or add it in the list of not found ones
if (!isset(self::$pharmacies[$code_client])) {
if (!isset(self::$pharmacies_fixeds[$code_client])) {
self::$pharmacies_notfound[$code_client] = 1;
// continue reading CSV
// don't add this code into the corrected result list
return true;
}
$code_client = self::$pharmacies_fixeds[$code_client];
}
// create the line in the bilan
if (!isset(self::$bilan[$code_client])) {
self::$bilan[$code_client] = array();
}
if (!isset(self::$bilan[$code_client][$low_module_name])) {
self::$bilan[$code_client][$low_module_name] = 0;
}
// update the "success" total for the current code
if (self::isValueValidated($cols[self::COL_STATUS])) {
self::$bilan[$code_client][$low_module_name]++;
$cols[self::COL_VALIDE] = 'oui';
}
else {
$cols[self::COL_VALIDE] = 'non';
}
// add the result line in the corrected results list (with the corrected code)
$cols[self::COL_CODE_CLIENT] = $code_client;
self::$results_corrected[] = $cols->toArray();
// continue reading CSV
return true;
}
static function isValueValidated($value)
{
if (empty($value)) {
return false;
}
$value = preg_replace('/é|É/', 'e', $value);
return strtolower($value) == "termine";
}
static function exportCorrectedResults(array $header, CSVWriter $csv_output)
{
$csv_output->setHeader(array_keys($header));
foreach(self::$results_corrected as $row) {
$csv_output->addLine($row);
}
}
static function exportResults(CSVWriter $csv_output)
{
// init total and export header
$total = array();
$row = array('Codes clients');
foreach (self::$modules as $category_name => $category_modules) {
foreach ($category_modules as $module_name) {
$row[] = $module_name;
$total[$module_name] = 0;
}
$row[] = 'Module '.$category_name;
$total[$category_name] = 0;
}
$csv_output->setHeader($row);
// export lines
foreach (self::$bilan as $code_client => $results) {
$row = array($code_client);
foreach (self::$modules as $category_name => $category_modules) {
$result_min = -1;
foreach ($category_modules as $module_name) {
$low_module_name = strtolower($module_name);
if (!isset($results[$low_module_name])) {
$result_min = 0;
$result = 0;
}
else {
if ($result_min == -1 || $result_min > $results[$low_module_name]) {
$result_min = $results[$low_module_name];
}
$result = $results[$low_module_name];
}
$row[] = $result;
$total[$module_name] += $result;
}
$row[] = $result_min;
$total[$category_name] += $result_min;
}
$csv_output->addLine($row);
}
// export total
$row = array('Total général');
foreach (self::$modules as $category_name => $category_modules) {
foreach ($category_modules as $module_name) {
$row[] = $total[$module_name];
}
$row[] = $total[$category_name];
}
$csv_output->setFooter($row);
}
}

View File

@ -0,0 +1,158 @@
<?php
require_once(__DIR__.'/ArrayExtended.php');
class TrainingFixedCodeClient extends ObjectModel
{
public $id_training_fixedcodeclient;
public $codeclient_from_results;
public $codeclient_fixed;
const CODE_CLIENT_WRONG = 1;
const CODE_CLIENT_RIGHT = 2;
const CODE_EMPTY = "__code_vide__";
private static $header = array(
'CC faux'=>self::CODE_CLIENT_WRONG,
'CC bon'=>self::CODE_CLIENT_RIGHT
);
public static $definition = array(
'table' => 'training_fixedcodeclient',
'primary' => 'id_training_fixedcodeclient',
'multilang' => false,
'fields' => array(
'id_training_fixedcodeclient' => array('type' => self::TYPE_INT, 'validate' => 'isInt'),
'codeclient_from_results' => array('type' => self::TYPE_STRING, 'lang' => false, 'validate' => 'isString'),
'codeclient_fixed' => array('type' => self::TYPE_STRING, 'lang' => false, 'validate' => 'isString'),
),
);
static function exportIntoCsvFile($file_path)
{
$csv_output = new CSVWriter($file_path);
$csv_output->setHeader(array_keys(self::$header));
$sql = 'SELECT `codeclient_from_results`, `codeclient_fixed`
FROM `'._DB_PREFIX_.'training_fixedcodeclient`
';
foreach (Db::getInstance()->executeS($sql) as $row) {
$csv_output->addLine(array($row['codeclient_from_results'], $row['codeclient_fixed']));
}
$csv_output->save();
}
static function importFromCsvFile($file_path)
{
$imported_codes = array();
$reader = new CSVReader($file_path);
$ok = $reader
->setExpectedHeader(self::$header)
->setOnEachLine(function(ArrayExtended $cols) use (&$imported_codes) {
$wrong_code = strtolower((string)$cols[self::CODE_CLIENT_WRONG]);
$right_code = strtolower((string)$cols[self::CODE_CLIENT_RIGHT]);
if (empty($wrong_code)) {
$wrong_code = self::CODE_EMPTY;
}
$imported_codes[$wrong_code] = $right_code;
return true;
})
->readLines();
if ($ok && count($imported_codes)>0) {
$existing_codes = array();
// load all already saved codes
foreach (Db::getInstance()->executeS('
SELECT `codeclient_from_results`, `codeclient_fixed`
FROM `'._DB_PREFIX_.'training_fixedcodeclient`
') as $row) {
$existing_codes[$row['codeclient_from_results']] = $row['codeclient_fixed'];
}
// insert new wrong codes with their correction
$values = array();
foreach(array_diff_key($imported_codes, $existing_codes) as $wrong_code => $right_code) {
$values[] = '(\''.pSql($wrong_code).'\', \''.pSql($right_code).'\')';
}
if (count($values)>0) {
$ok = Db::getInstance()->execute('
INSERT INTO `'._DB_PREFIX_.'training_fixedcodeclient`
(`codeclient_from_results`, `codeclient_fixed`)
VALUES
'.implode(',', $values).'
');
}
// replace existing uncorrected code with their correction
foreach(array_intersect_key($imported_codes, $existing_codes) as $wrong_code => $right_code) {
$ok = $ok && Db::getInstance()->execute('
UPDATE `'._DB_PREFIX_.'training_fixedcodeclient`
SET `codeclient_fixed` = \''.pSql($right_code).'\'
WHERE `codeclient_from_results` = \''.pSql($wrong_code).'\'
');
}
}
unset($imported_codes);
return $ok;
}
static function loadOnlyFixed()
{
$result = new ArrayExtended();
$sql = 'SELECT `codeclient_from_results`, `codeclient_fixed`
FROM `'._DB_PREFIX_.'training_fixedcodeclient`
WHERE codeclient_fixed <> \'\'';
foreach (Db::getInstance()->executeS($sql) as $row) {
$result[$row['codeclient_from_results']] = $row['codeclient_fixed'];
}
return $result;
}
static function addIfNotExist(array $pharmacies_not_found)
{
// get already saved codes to correct
$existing_codes = array();
$sql = 'SELECT LOWER(`codeclient_from_results`) as `codeclient_from_results`
FROM `'._DB_PREFIX_.'training_fixedcodeclient`';
foreach (Db::getInstance()->executeS($sql) as $row) {
$existing_codes[] = $row['codeclient_from_results'];
}
// remove duplicate keys
$unique_pharmacies_not_found = array();
foreach ($pharmacies_not_found as $key => $val) {
$key = strtolower($key);
if (!isset($unique_pharmacies_not_found[$key])) {
$unique_pharmacies_not_found[$key] = $val;
}
}
$unique_pharmacies_not_found = array_keys($unique_pharmacies_not_found);
// filter new codes not already present in DB (and create the SQL value string)
$values = array();
foreach(array_diff($unique_pharmacies_not_found, $existing_codes) as $code_client) {
$values[] = '\''.pSql((string)$code_client).'\', \'\'';
}
// if any new codes, add them
if (count($values)>0) {
Db::getInstance()->execute(
'INSERT INTO `'._DB_PREFIX_.'training_fixedcodeclient`
(codeclient_from_results, codeclient_fixed)
VALUES
('.implode('),(', $values).')'
);
}
}
}

View File

@ -0,0 +1,88 @@
<?php
require_once __DIR__.'/CSVReader.php';
class TrainingModule extends ObjectModel
{
const MODULE_NAME = 0;
const CATEGORY_NAME = 1;
public $id_training_module;
public $module_name;
public $category_name;
public static $definition = array(
'table' => 'training_module',
'primary' => 'id_training_module',
'multilang' => false,
'fields' => array(
'id_training_module' => array('type' => self::TYPE_INT, 'validate' => 'isInt'),
'module_name' => array('type' => self::TYPE_STRING, 'lang' => false, 'validate' => 'isString'),
'category_name' => array('type' => self::TYPE_STRING, 'lang' => false, 'validate' => 'isString'),
),
);
private static $failed_line_number = 0;
static function importFromCsvFile($file_path)
{
$values = array();
$reader = new CSVReader($file_path);
$ok = $reader
->enableSkipHeader()
->setExpectedHeader(array(
'Modules' => self::MODULE_NAME,
'Catégories'=>self::CATEGORY_NAME
))
->setOnStart(function() {
self::deleteAll();
})
->setOnEachLine(function(ArrayExtended $cols) use (&$values) {
$values[] = '\''.pSql((string)$cols[self::MODULE_NAME]).'\', \''.pSql((string)$cols[self::CATEGORY_NAME]).'\'';
return true;
})
->setOnError(function($failed_line_number) {
self::$failed_line_number = $failed_line_number;
self::deleteAll();
})
->readLines();
if ($ok && count($values)>0) {
$ok = Db::getInstance()->execute('
INSERT INTO `'._DB_PREFIX_.'training_module`
(`module_name`, `category_name`)
VALUES
('.implode('),(', $values).')
');
}
unset($values);
return $ok;
}
static function deleteAll()
{
Db::getInstance()->execute('TRUNCATE `'._DB_PREFIX_.'training_module`');
}
static function hasAnyRow()
{
return Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'training_module`') > 0;
}
static function loadAll()
{
$result = array();
$sql = 'SELECT `module_name`, `category_name`
FROM `'._DB_PREFIX_.'training_module`
ORDER BY `category_name` ASC, `module_name` ASC';
foreach (Db::getInstance()->executeS($sql) as $row) {
if (!isset($result[$row['category_name']])) {
$result[$row['category_name']] = array();
}
$result[$row['category_name']][] = $row['module_name'];
}
return new ArrayExtended($result);
}
}

View File

@ -0,0 +1,81 @@
<?php
require_once(__DIR__.'/CSVReader.php');
class TrainingPharmacy extends ObjectModel
{
const CODE_CLIENT = 1;
public $id_training_pharmacy;
public $codeclient;
public static $definition = array(
'table' => 'training_pharmacy',
'primary' => 'id_training_pharmacy',
'multilang' => false,
'fields' => array(
'id_training_pharmacy' => array('type' => self::TYPE_INT, 'validate' => 'isInt'),
'codeclient' => array('type' => self::TYPE_STRING, 'lang' => false, 'validate' => 'isString'),
),
);
private static $failed_line_number = 0;
static function importFromCsvFile($file_path)
{
$values = array();
$reader = new CSVReader($file_path);
$ok = $reader
->enableSkipHeader()
->setExpectedHeader(array(
'CodeClt'=>self::CODE_CLIENT
))
->setOnStart(function() {
self::deleteAll();
})
->setOnEachLine(function(ArrayExtended $cols) use (&$values) {
$values[] = '\''.pSql((string)$cols[self::CODE_CLIENT]).'\'';
return true;
})
->setOnError(function($failed_line_number) {
self::$failed_line_number = $failed_line_number;
self::deleteAll();
})
->readLines();
if ($ok && count($values)>0) {
$ok = Db::getInstance()->execute('
INSERT INTO `'._DB_PREFIX_.'training_pharmacy`
(`codeclient`)
VALUES
('.implode('),(', $values).')
');
}
unset($values);
return $ok;
}
static function deleteAll()
{
Db::getInstance()->execute('TRUNCATE `'._DB_PREFIX_.'training_pharmacy`');
}
static function hasAnyRow()
{
return Db::getInstance()->getValue('SELECT COUNT(*) FROM `'._DB_PREFIX_.'training_pharmacy`') > 0;
}
static function loadAll()
{
$result = new ArrayExtended();
$sql = 'SELECT `codeclient`, `id_training_pharmacy`
FROM `'._DB_PREFIX_.'training_pharmacy`';
foreach (Db::getInstance()->executeS($sql) as $row) {
$result[$row['codeclient']] = $row['id_training_pharmacy'];
}
return $result;
}
}

68
modules/training/test.php Normal file
View File

@ -0,0 +1,68 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
require_once(__DIR__.'/models/CSVReader.php');
function debug($var)
{
echo "<pre>";
print_r($var);
echo "</pre>";
}
$original = new ArrayExtended();
$original_score = new ArrayExtended();
$reader = new CSVReader(__DIR__.'/upload/Bilan_original.csv');
$reader ->skipHeader()
->onEachLine(function(ArrayExtended $cols) use($original, $original_score) {
$original[] = $cols[0];
$original_score[] = $cols[1];
return true;
})
->onError(function($failed_num_line) {
debug($failed_num_line);
})
->read();
$new_version = new ArrayExtended();
$new_version_score = new ArrayExtended();
$reader = new CSVReader(__DIR__.'/upload/BILAN.csv');
$reader ->skipHeader()
->setDelimiter("\"")
->onEachLine(function(ArrayExtended $cols) use($new_version, $new_version_score) {
$new_version[] = $cols[0];
$new_version_score[] = $cols[1];
return true;
})
->onError(function($failed_num_line) {
debug($failed_num_line);
})
->read();
$original = $original->toArray();
$original_score = $original_score->toArray();
$new_version = $new_version->toArray();
$new_version_score = $new_version_score->toArray();
//debug($new_version);
//debug(array_diff_assoc($new_version, $original));
//debug(array_diff_assoc($original, $new_version));
$diff = array();
foreach(array_diff($original, $new_version) as $i => $code_client) {
$diff[$code_client] = $original_score[$i];
}
debug($diff);
/*
$diff = array();
foreach(array_diff($new_version, $original) as $i => $code_client) {
$diff[$code_client] = $new_version_score[$i];
}
debug($diff);
*/

View File

@ -0,0 +1,167 @@
<?php
if (!defined('_PS_VERSION_'))
exit;
include_once(_PS_MODULE_DIR_.'training/models/TrainingModule.php');
include_once(_PS_MODULE_DIR_.'training/models/TrainingPharmacy.php');
include_once(_PS_MODULE_DIR_.'training/models/TrainingFixedCodeClient.php');
class Training extends Module
{
public function __construct(){
$this->name = 'training';
$this->tab = 'administration';
$this->version = '1.0';
$this->author = 'Antadis';
$this->need_instance = 0;
parent::__construct();
$this->displayName = $this->l('Analyse formation en ligne');
$this->description = $this->l('Permet d\'importer les résultats de la formation en ligne et d\'en extraire un bilan');
$this->confirmUninstall = $this->l('Etes vous sur de vouloir désinstaller ce module ?');
}
public function install()
{
if (!parent::install()) {
return false;
}
$queries = array(
'CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'training_module` (
`id_training_module` int(11) NOT NULL AUTO_INCREMENT,
`module_name` VARCHAR(255) NOT NULL,
`category_name` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id_training_module`),
UNIQUE(`module_name`)
) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8',
'CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'training_pharmacy` (
`id_training_pharmacy` int(11) NOT NULL AUTO_INCREMENT,
`codeclient` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id_training_pharmacy`)
) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8',
'CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'training_fixedcodeclient` (
`id_training_fixedcodeclient` int(11) NOT NULL AUTO_INCREMENT,
`codeclient_from_results` VARCHAR(255) NOT NULL,
`codeclient_fixed` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id_training_fixedcodeclient`),
UNIQUE(`codeclient_from_results`)
) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8'
);
if (!self::dbExecute($queries)) {
$this->uninstall();
return false;
}
$tab = new Tab();
$tab->class_name = 'AdminTrainingRoot';
$tab->id_parent = 0;
$tab->module = $this->name;
$tab->name[(int)Configuration::get('PS_LANG_DEFAULT')] = $this->l('Analyse formation en ligne');
if (!$tab->add()) {
$this->uninstall();
return false;
}
$tab = new Tab();
$tab->class_name = 'AdminTraining';
$tab->id_parent = (int)Tab::getIdFromClassName('AdminTrainingRoot');
$tab->module = $this->name;
$tab->name[(int)Configuration::get('PS_LANG_DEFAULT')] = $this->l('Analyse formation en ligne');
if (!$tab->add()) {
$this->uninstall();
return false;
}
$tab = new Tab();
$tab->class_name = 'AdminTrainingModules';
$tab->id_parent = (int)Tab::getIdFromClassName('AdminTrainingRoot');
$tab->module = $this->name;
$tab->name[(int)Configuration::get('PS_LANG_DEFAULT')] = $this->l('Modules/Catégories formation');
if (!$tab->add()) {
$this->uninstall();
return false;
}
$tab = new Tab();
$tab->class_name = 'AdminTrainingPharmacy';
$tab->id_parent = (int)Tab::getIdFromClassName('AdminTrainingRoot');
$tab->module = $this->name;
$tab->name[(int)Configuration::get('PS_LANG_DEFAULT')] = $this->l('Pharmacies');
if (!$tab->add()) {
$this->uninstall();
return false;
}
$tab = new Tab();
$tab->class_name = 'AdminTrainingFixedCodeClient';
$tab->id_parent = (int)Tab::getIdFromClassName('AdminTrainingRoot');
$tab->module = $this->name;
$tab->name[(int)Configuration::get('PS_LANG_DEFAULT')] = $this->l('Correction codes clients');
if (!$tab->add()) {
$this->uninstall();
return false;
}
return true;
}
public function uninstall()
{
self::dbExecute(array(
'DROP TABLE IF EXISTS `'._DB_PREFIX_.'training_module`',
'DROP TABLE IF EXISTS `'._DB_PREFIX_.'training_pharmacy`',
'DROP TABLE IF EXISTS `'._DB_PREFIX_.'training_fixedcodeclient`'
));
Configuration::deleteByName('TRAINING_USED_MODULE_FILE');
Configuration::deleteByName('TRAINING_USED_PHARMACY_FILE');
Configuration::deleteByName('TRAINING_USED_RESULT_FILE');
Configuration::deleteByName('TRAINING_FIXEDCODES_FILE');
Configuration::deleteByName('TRAINING_BILAN_FILE');
Configuration::deleteByName('TRAINING_CORRECTED_RESULT_FILE');
Configuration::deleteByName('TRAINING_CORRECTED_CODES_FILE');
$tab = new Tab(Tab::getIdFromClassName('AdminTrainingFixedCodeClient'));
$tab->delete();
$tab = new Tab(Tab::getIdFromClassName('AdminTrainingPharmacy'));
$tab->delete();
$tab = new Tab(Tab::getIdFromClassName('AdminTrainingModules'));
$tab->delete();
$tab = new Tab(Tab::getIdFromClassName('AdminTraining'));
$tab->delete();
$tab = new Tab(Tab::getIdFromClassName('AdminTrainingRoot'));
$tab->delete();
return parent::uninstall();
}
private static function dbExecute(array $queries){
foreach($queries as $query){
if( !Db::getInstance()->execute($query)){
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,171 @@
<h1>{l s='Analyse de formations en ligne' mod='training'}</h1>
<div>
- L'intitulé des colonnes des fichiers doit être identique à ce qui est indiqué dans les commentaires "Entête/colonnes obligatoires" (à l'espace près entre les termes).<br />
La casse n'a pas d'importante (majuscules / minuscules).
<br /><br />
- Les noms de catégories et modules doivent être identiques entre le fichier "modules/catégories" et le fichier "résultats"
sinon le générateur de bilan ne pourra pas retrouver ces informations.
<br />
La casse n'a pas d'importante ici aussi (majuscules / minuscules).
</div>
<br />
<br />
<form method="post" action="{$link_self}" name="uploadModules" class="defaultForm" enctype="multipart/form-data">
<fieldset>
<legend>{l s='1 - Modules/Catégories' mod='training'}</legend>
<label>Entête/Colonnes obligatoires :</label>
<div class="margin-form">
- Modules<br />
- Catégories
</div>
<br />
<label for="module_filename">{l s='Importer un csv contenant les modules/catégories ' mod='training'} :</label>
<div class="margin-form">
<input type="file" name="module_filename">
</div>
<div class="margin-form">
<input class="button" type="submit" name="submitFileModules" value="Importer les modules/catégories">
</div>
<label for="">{l s='Fichier actuellement utilisé' mod='training'} :</label>
{if isset($used_module_file) && $used_module_file!=''}
<div class="margin-form"><a href='{$url_upload_path}{$used_module_file}' target='_blank'>{$used_module_file}</a></div>
{else}
<div class="margin-form"> aucun </div>
{/if}
</fieldset>
<br />
</form>
<form method="post" action="{$link_self}" name="uploadPharmacy" class="defaultForm" enctype="multipart/form-data">
<fieldset>
<legend>{l s='2 - Pharmacies' mod='training'}</legend>
<label>Entête/Colonnes obligatoires :</label>
<div class="margin-form">
- CodeClt<br />
</div>
<br />
<label for="pharmacy_filename">{l s='Importer un csv contenant les pharmacies avec leur code client' mod='training'} :</label>
<div class="margin-form">
<input type="file" name="pharmacy_filename">
</div>
<div class="margin-form">
<input class="button" type="submit" name="submitFilePharmacies" value="Importer les pharmacies">
</div>
<label for="">{l s='Fichier actuellement utilisé' mod='training'} :</label>
{if isset($used_pharmacy_file) && $used_pharmacy_file!=''}
<div class="margin-form"><a href='{$url_upload_path}{$used_pharmacy_file}' target='_blank'>{$used_pharmacy_file}</a></div>
{else}
<div class="margin-form">- aucun -</div>
{/if}
</fieldset>
</form>
<br />
<form method="post" action="{$link_self}" name="uploadFixedCodes" class="defaultForm" enctype="multipart/form-data">
<fieldset>
<legend>{l s='3 - Codes corrigés (facultatif)' mod='training'}</legend>
<label>Entête/Colonnes obligatoires :</label>
<div class="margin-form">
- CC faux<br />
- CC bon
</div>
<br />
<label for="fixed_codes_filename">{l s='Importer un csv contenant les codes faux et leur correction' mod='training'} :</label>
<div class="margin-form">
<input type="file" name="fixed_codes_filename">
</div>
<div class="margin-form">
<input class="button" type="submit" name="submitFileFixedCodes" value="Importer et mettre à jour les codes corrigés">
</div>
<label for="">{l s='Dernier fichier importé' mod='training'} :</label>
{if isset($used_fixedcodes_file) && $used_fixedcodes_file!=''}
<div class="margin-form"><a href='{$url_upload_path}{$used_fixedcodes_file}' target='_blank'>{$used_fixedcodes_file}</a></div>
{else}
<div class="margin-form">- aucun -</div>
{/if}
</fieldset>
</form>
<br />
<fieldset>
<legend>{l s='LE BILAN' mod='training'}</legend>
<form method="post" action="{$link_self}" name="uploadResults" class="defaultForm" enctype="multipart/form-data">
<label>Entête/Colonnes obligatoires :</label>
<div class="margin-form">
- Module<br />
- Code Client<br />
- Prenom<br />
- NOM<br />
- Telephone<br />
- Nom pharmacie<br />
- Ville<br />
- Date<br />
- Statut<br />
</div>
<br />
<label for="results_filename">{l s='Importer un fichier csv contenant les résultats ' mod='training'} :</label>
<div class="margin-form">
<input type="hidden" name="MAX_FILE_SIZE" value="16000000" />
<input type="file" name="results_filename"> (taille max : 16 Mo)
</div>
<div class="margin-form">
<input class="button" type="submit" id="submitFileResults" name="submitFileResults" value="Transmettre le fichier de résultats">
</div>
<label for="">{l s='Fichier actuellement utilisé' mod='training'} :</label>
{if isset($used_results_file) && $used_results_file!=''}
<div class="margin-form"><a href='{$url_upload_path}{$used_results_file}' target='_blank'>{$used_results_file}</a></div>
{else}
<div class="margin-form">- aucun -</div>
{/if}
</form>
</fieldset>
<fieldset>
<form method="post" action="{$link_self}" name="generateBilan" class="defaultForm">
<div class="margin-form">
<input class="button" type="submit" name="generateBilan" value="{if isset($bilan_file) && $bilan_file!=''}RE-{/if}GENERER LE BILAN">
</div>
<div id='links_result_files'>
{if isset($bilan_file) && $bilan_file!=''}
<label></label>
<div class="margin-form"><a href='{$url_output_path}{$bilan_file}' target='_blank'>Télécharger le dernier bilan : {$bilan_file}</a></div>
{/if}
{if isset($corrected_results_file) && $corrected_results_file!=''}
<label></label>
<div class="margin-form"><a href='{$url_output_path}{$corrected_results_file}' target='_blank'>Télécharger le dernier résultat corrigé : {$corrected_results_file}</a></div>
{/if}
{if isset($corrected_codes_file) && $corrected_codes_file!=''}
<label></label>
<div class="margin-form"><a href='{$url_output_path}{$corrected_codes_file}' target='_blank'>Télécharger les derniers codes corrigés : {$corrected_codes_file}</a></div>
{/if}
</div>
</form>
</fieldset>