Aggiunto modulo per l'importazione CSV

This commit is contained in:
Thomas Zilio 2018-02-23 19:04:05 +01:00
parent f09b0ea070
commit d5c513f9e5
8 changed files with 424 additions and 3 deletions

View File

@ -22,10 +22,8 @@
"type": "project",
"require": {
"php": ">=5.6",
"ext-mbstring": "*",
"ext-pdo_mysql": "*",
"aluguest/ical-easy-reader": "^1.5",
"danielstjules/stringy": "^3.1",
"ezyang/htmlpurifier": "^4.8",
@ -33,6 +31,7 @@
"ifsnop/mysqldump-php": "^2.3",
"intervention/image": "^2.3",
"ircmaxell/password-compat": "^1.0",
"league/csv": "^8.2",
"maximebf/debugbar": "^1.15",
"monolog/monolog": "^1.22",
"mpdf/mpdf": "^7.0",

View File

@ -0,0 +1,101 @@
<?php
include_once __DIR__.'/../../core.php';
switch (post('op')) {
case 'import':
foreach ($data as $key => $value) {
unset($value['tipologia']);
$dbo->insert('an_anagrafiche', $value);
// Aggiornamento della tipologia di anagrafiche
$dbo->sync('an_tipianagrafiche_anagrafiche', [
'idanagrafica' => $dbo->lastInsertedID(),
], [
'idtipoanagrafica' => (array) $data[$key]['tipologia'],
]);
}
break;
}
return [
[
'field' => 'codice',
'label' => 'Codice',
],
[
'field' => 'ragione_sociale',
'label' => 'Ragione sociale',
],
[
'field' => 'provincia',
'label' => 'Provincia',
],
[
'field' => 'citta',
'label' => 'Città',
],
[
'field' => 'telefono',
'label' => 'Telefono',
],
[
'field' => 'indirizzo',
'label' => 'Indirizzo',
],
[
'field' => 'cap',
'label' => 'CAP',
],
[
'field' => 'cellulare',
'label' => 'Cellulare',
],
[
'field' => 'fax',
'label' => 'Fax',
],
[
'field' => 'email',
'label' => 'Email',
],
[
'field' => 'codice_fiscale',
'label' => 'Codice Fiscale',
],
[
'field' => 'piva',
'label' => 'Partita IVA',
],
[
'field' => 'codiceiban',
'label' => 'IBAN',
],
[
'field' => 'note',
'label' => 'Note',
],
[
'field' => 'id_nazione',
'label' => 'Nazione',
'other' => 'nazione',
'query' => 'SELECT id as result FROM an_nazioni WHERE LOWER(nome) = LOWER(|value|)',
],
[
'field' => 'idagente',
'label' => 'ID Agente',
],
[
'field' => 'idpagamento_vendite',
'label' => 'ID Pagamento',
'other' => 'idpagamento',
],
[
'field' => 'tipologia',
'label' => 'Tipologia',
'other' => 'idtipo',
'query' => 'SELECT idtipoanagrafica as result FROM an_tipianagrafiche WHERE descrizione = |value|',
],
];

View File

@ -0,0 +1,54 @@
<?php
include_once __DIR__.'/../../core.php';
switch (post('op')) {
case 'import':
$first_row = post('first_row');
$selected = post('fields');
// Pulizia dei campi inutilizzati
foreach ($selected as $key => $value) {
if (!is_numeric($value)) {
unset($selected[$key]);
}
}
$fields = Import::getFields($id_record);
$csv = Import::getFile($id_record, $records[0]['id'], [
'headers' => empty($first_row),
]);
// Interpretazione dei dati
$data = [];
foreach ($csv as $row) {
$data_row = [];
foreach ($row as $key => $value) {
$field = $fields[$selected[$key]];
if (isset($selected[$key])) {
$name = $field['field'];
$query = $field['query'];
if (!empty($query)) {
$query = str_replace('|value|', prepare($value), $query);
$value = $dbo->fetchArray($query)[0]['result'];
}
$data_row[$name] = $value;
}
}
$data[] = $data_row;
}
// Richiamo delle operazioni specifiche
include $imports[$id_record]['import'];
$_SESSION['infos'][] = tr('Importazione completata!');
break;
}

34
modules/import/add.php Normal file
View File

@ -0,0 +1,34 @@
<?php
include_once __DIR__.'/../../core.php';
$list = [];
foreach ($imports as $key => $value) {
$list[] = [
'id' => $key,
'text' => $value['title'],
];
}
// Utilizzo le funzionalità di filelist_and_upload
?><form action="" method="post" id="add-form" enctype="multipart/form-data">
<input type="hidden" name="op" value="link_file">
<input type="hidden" name="backto" value="record-edit">
<div class="row">
<div class="col-md-6">
{[ "type": "file", "label": "<?php echo tr('File'); ?>", "name": "blob", "required": 1 ]}
</div>
<div class="col-md-6">
{[ "type": "select", "label": "<?php echo tr('Modulo'); ?>", "name": "id_record", "values": <?php echo json_encode($list); ?> ]}
</div>
</div>
<!-- PULSANTI -->
<div class="row">
<div class="col-md-12 text-right">
<button type="submit" class="btn btn-primary"><i class="fa fa-plus"></i> <?php echo tr('Aggiungi'); ?></button>
</div>
</div>
</form>

94
modules/import/edit.php Normal file
View File

@ -0,0 +1,94 @@
<?php
include_once __DIR__.'/../../core.php';
if (empty($id_record)) {
require $docroot.'/add.php';
} else {
echo '
<form action="" method="post" id="edit-form">
<input type="hidden" name="backto" value="record-list">
<input type="hidden" name="op" value="import">
<div class="row">
<div class="col-md-12">
{[ "type": "checkbox", "label": "'.tr('Importa prima riga').'", "name": "first_row" ]}
</div>
</div>';
// Inclusione del file del modulo per eventuale HTML personalizzato
include $imports[$id_record]['import'];
$fields = Import::getFields($id_record);
$select = [];
foreach ($fields as $key => $value) {
$select[] = [
'id' => $key,
'text' => $value['label'],
];
}
$rows = Import::getFile($id_record, $records[0]['id'], [
'limit' => 10,
]);
$count = count($rows[0]);
echo '
<div class="row">';
for ($column = 0; $column < $count; ++$column) {
echo '
<div class="col-sm-6 col-lg-4">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">'.tr('Colonna _NUM_', [
'_NUM_' => $column + 1,
]).'</h3>
</div>
<div class="panel-body">';
// Individuazione delle corrispondenze
$selected = null;
foreach ($fields as $key => $value) {
if (in_array($rows[0][$column], $value)) {
$selected = $key;
break;
}
}
echo '
{[ "type": "select", "label": "'.tr('Campo').'", "name": "fields[]", "values": '.json_encode($select).', "value": "'.$selected.'" ]}
<table class="table table-striped">
<thead>
<tr>
<th>'.tr('#').'</th>
<th>'.tr('Valore').'</th>
</tr>
</thead>
<tbody>';
foreach ($rows as $key => $row) {
echo '
<tr>
<td>'.($key + 1).'</td>
<td>'.$row[$column].'</td>
</tr>';
}
echo '
</tbody>
</table>
</div>
</div>
</div>';
}
echo '
</div>
</form>';
}

9
modules/import/init.php Normal file
View File

@ -0,0 +1,9 @@
<?php
include_once __DIR__.'/../../core.php';
$imports = Import::getImports();
if (!empty($id_record)) {
$records = Import::get($id_record)['files'];
}

125
src/Import.php Normal file
View File

@ -0,0 +1,125 @@
<?php
/**
* Classe per la gestione delle utenze.
*
* @since 2.4
*/
class Import
{
/** @var int Identificativo del modulo corrente */
protected static $imports;
/**
* Restituisce tutte le informazioni di tutti i moduli installati.
*
* @return array
*/
public static function getImports()
{
if (empty(self::$imports)) {
$modules = Modules::getModules();
$database = Database::getConnection();
$results = [];
foreach ($modules as $module) {
$file = DOCROOT.'/modules/'.$module['directory'].'|custom|/import.php';
$original_file = str_replace('|custom|', '', $file);
$custom_file = str_replace('|custom|', '/custom', $file);
if (file_exists($custom_file) || file_exists($original_file)) {
$files = $database->fetchArray('SELECT * FROM zz_files WHERE id_module='.prepare(Modules::get('Import')['id']).' AND id_record='.prepare($module['id']).' ORDER BY id DESC');
$results[$module['id']] = array_merge($module, [
'import' => file_exists($custom_file) ? $custom_file : $original_file,
'files' => $files,
]);
}
}
self::$imports = $results;
}
return self::$imports;
}
/**
* Restituisce le informazioni relative a un singolo modulo specificato.
*
* @param string|int $module
*
* @return array
*/
public static function get($module)
{
if (!is_numeric($module) && !empty(self::getModules()[$module])) {
$module = self::getModules()[$module];
}
return self::getImports()[$module];
}
/**
* Restituisce l'elenco dei campi previsti dal modulo.
*
* @param string|int $module
*
* @return array
*/
public static function getFields($module)
{
$import = self::get($module);
ob_start();
$fields = require $import['import'];
ob_end_clean();
return $fields;
}
/**
* Restituisce i contenuti del file CSV indicato.
*
* @param string|int $module
* @param int $file_id
* @param array $options
*
* @return array
*/
public static function getFile($module, $file_id, $options = [])
{
$import = self::get($module);
$ids = array_column($import['files'], 'id');
$find = array_search($file_id, $ids);
if ($find == -1) {
return [];
}
$file = DOCROOT.'/files/'.Modules::get('Import')['directory'].'/'.$import['files'][$find]['filename'];
// Gestione del file CSV
$csv = League\Csv\Reader::createFromPath($file, 'r');
$csv->setDelimiter(';');
// Ignora la prima riga
$offset = 0;
if (!empty($options['headers'])) {
++$offset;
}
$rows = $csv->setOffset($offset);
// Limite di righe
if (!empty($options['limit'])) {
$rows = $rows->setLimit($options['limit']);
}
// Lettura
$rows = $rows->fetchAll();
return $rows;
}
}

View File

@ -180,7 +180,7 @@ UPDATE `co_documenti` SET `id_sezionale`='2' WHERE `idtipodocumento` IN (SELECT
-- Innesto modulo sezionali sotto "Contabilità"
INSERT INTO `zz_modules` (`id`, `name`, `title`, `directory`, `options`, `options2`, `icon`, `version`, `compatibility`, `order`, `parent`, `default`, `enabled`) VALUES
(NULL, 'Sezionali', 'Sezionali', 'sezionali', '{ "main_query": [ { "type": "table", "fields": "Tipo documenti, Nome, Maschera, Magazzino, Note", "query": "SELECT `id`, `nome` AS `Nome`, `maschera` AS `Maschera`, (SELECT nome FROM dt_automezzi WHERE dt_automezzi.id = idautomezzo) AS Magazzino, IF(`dir`=''entrata'', ''Documenti di vendita'', ''Documenti di acquisto'') AS `Tipo documenti`, `note` AS `Note` FROM `co_sezionali` HAVING 2=2 ORDER BY `Tipo documenti`, `Nome`"} ]}', '', 'fa fa-database', '2.2', '2.2', 1, 12, 1, 1);
(NULL, 'Sezionali', 'Sezionali', 'sezionali', '{ "main_query": [ { "type": "table", "fields": "Tipo documenti, Nome, Maschera, Magazzino, Note", "query": "SELECT `id`, `nome` AS `Nome`, `maschera` AS `Maschera`, (SELECT nome FROM dt_automezzi WHERE dt_automezzi.id = idautomezzo) AS Magazzino, IF(`dir`=''entrata'', ''Documenti di vendita'', ''Documenti di acquisto'') AS `Tipo documenti`, `note` AS `Note` FROM `co_sezionali` HAVING 2=2 ORDER BY `Tipo documenti`, `Nome`"} ]}', '', 'fa fa-database', '2.4', '2.4', 1, 12, 1, 1);
-- Aggiungo impostazione predefinita
INSERT INTO `zz_settings` (`idimpostazione`, `nome`, `valore`, `tipo`, `editable`, `sezione`) VALUES
@ -235,3 +235,8 @@ CREATE TABLE IF NOT EXISTS `zz_field_record` (
PRIMARY KEY (`id`),
FOREIGN KEY (`id_field`) REFERENCES `zz_fields`(`id`) ON DELETE CASCADE
);
-- Aggiunta modulo di importazione
INSERT INTO `zz_modules` (`id`, `name`, `title`, `directory`, `options`, `options2`, `icon`, `version`, `compatibility`, `order`, `parent`, `default`, `enabled`) VALUES
(NULL, 'Import', 'Import', 'import', 'custom', '', 'fa fa-file-o', '2.4', '2.4', 1, NULL, 1, 1);
UPDATE `zz_modules` `t1` INNER JOIN `zz_modules` `t2` ON (`t1`.`name` = 'Import' AND `t2`.`name` = 'Strumenti') SET `t1`.`parent` = `t2`.`id`;