Aggiunto mappatura e prototipo filtro

This commit is contained in:
Amministratore 2025-08-06 19:28:01 +02:00
parent a1742e4e61
commit 652f9a7e76
12 changed files with 215 additions and 29 deletions

View File

@ -2,6 +2,7 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Categorie;
use App\Models\ImportRule; use App\Models\ImportRule;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@ -13,6 +14,8 @@ class ImportRuleController extends Controller
public function index() public function index()
{ {
// //
$rules = ImportRule::all();
return view('import_rules.index', compact('rules'));
} }
/** /**
@ -21,6 +24,11 @@ class ImportRuleController extends Controller
public function create() public function create()
{ {
// //
// Return a view to create a new import rule
$categorie = Categorie::all();
return view('import_rules.create',compact('categorie'));
//'categories'=>$categorie);
} }
/** /**
@ -29,6 +37,15 @@ class ImportRuleController extends Controller
public function store(Request $request) public function store(Request $request)
{ {
// //
$request->validate([
'pattern' => 'required|string|max:255',
'category_id' => 'required|exists:categories,id',
'description' => 'nullable|string|max:255',
'is_active' => 'boolean',
'created_by' => 'nullable|string|max:255',
]);
ImportRule::create($request->all());
return redirect()->route('import_rules.index'); // Redirect to the index after storing the rule
} }
/** /**

View File

@ -13,9 +13,14 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Rap2hpoutre\FastExcel\FastExcel; use Rap2hpoutre\FastExcel\FastExcel;
use Illuminate\Support\Facades\Storage;
use DateTime;
class MovimentiController extends Controller class MovimentiController extends Controller
{ {
public $map;
// Gestione dei movimenti // Gestione dei movimenti
public static function newMovimenti() { public static function newMovimenti() {
$categorie=Categorie::list(); // TODO: da risolvere con jquery nella pagina blade conti.movimenti.list $categorie=Categorie::list(); // TODO: da risolvere con jquery nella pagina blade conti.movimenti.list
@ -354,21 +359,41 @@ class MovimentiController extends Controller
public function importmappedCsv(Request $request) public function importmappedCsv(Request $request)
{ {
//$request->mov_data //$request->mov_data
foreach($request->mapped as $key => $value) $mapped=$request['mapping'];
foreach( $mapped as $key => $value)
{ {
if($value!=null) if($value!=null)
{ {
$map=array( $this->map[$key]=$value;
$csv_field=$key, $collection = collect($this->map);
$db_field=$value, }
);
dd($map);
}
$mappdCvs=(new FastExcel)->configureCsv(';')->create($request->filename .".new.csv",);
} }
dd($request); //dd ($this->map,$collection);
$mappdCvs=(new FastExcel)->configureCsv(';')->import(
Storage::path($request->filename), function($line){
if(isset($line[$this->map['mov_data']]))
{
Movimenti::create (
['mov_data' => DateTime::createFromFormat(
'd/m/Y',$line[$this->map['mov_data']]),
'mov_descrizione' => $line[$this->map['mov_descrizione']],
'mov_importo_dare' => $line[$this->map['mov_importo_dare']],
'mov_importo_avere' => $line[$this->map['mov_importo_avere']],
'mov_fk_categoria' => '1',
'mov_fk_tags' => 1,
'mov_inserito_da' => Auth::id(),
'conto_id_da' => 1
,'conto_id_a' => 1,
]
);
};
});
// dd($map,$mapped,$request,$collection);
// dd($request);
return redirect(Route('movimenti'));
} }
public function importFile() public function importFile()

View File

@ -8,4 +8,8 @@ use Illuminate\Database\Eloquent\Model;
class ImportRule extends Model class ImportRule extends Model
{ {
use HasFactory; use HasFactory;
// In MovimentiController o direttamente nel model Movimenti
} }

View File

@ -18,6 +18,18 @@ class Movimenti extends Model
protected $dates = ['mov_data']; protected $dates = ['mov_data'];
protected $casts = [ 'mov_data'=>'datetime']; protected $casts = [ 'mov_data'=>'datetime'];
protected $fillable = [
'mov_data',
'mov_fk_categoria',
'mov_descrizione',
'mov_importo_dare',
'mov_importo_avere',
'mov_inserito_da',
'mov_fk_tags',
'conto_id_da',
'conto_id_a'
];
public static $query= 'SELECT public static $query= 'SELECT
a.id, a.id,
a.mov_data, a.mov_data,
@ -57,7 +69,8 @@ JOIN categories as c ON a.mov_fk_categoria=c.id';
'SELECT 'SELECT
a.id, a.id,
a.mov_data, a.mov_data,
a.mov_importo, a.mov_importo_dare,
a.mov_importo_avere,
a.mov_descrizione, a.mov_descrizione,
c.cat_name, c.cat_name,
t.tag_name, t.tag_name,
@ -66,7 +79,7 @@ JOIN categories as c ON a.mov_fk_categoria=c.id';
FROM movimentis as a FROM movimentis as a
JOIN tags as t ON a.mov_fk_tags=t.id JOIN tags as t ON a.mov_fk_tags=t.id
JOIN categories as c ON a.mov_fk_categoria=c.id JOIN categories as c ON a.mov_fk_categoria=c.id
JOIN contos as co ON a.conto_id=co.id' JOIN contos as co ON a.conto_id_da=co.id'
); );
$query = $expression->getValue(DB::connection()->getQueryGrammar()); $query = $expression->getValue(DB::connection()->getQueryGrammar());
@ -335,10 +348,12 @@ JOIN categories as c ON a.mov_fk_categoria=c.id';
return [ return [
"Data movimento"=>"mov_data", "Data movimento"=>"mov_data",
"Descrizione"=>"mov_descrizione", "Descrizione"=>"mov_descrizione",
"Importo"=>"mov_importo", "Importo Dare"=>"mov_importo_dare",
"Importo Avere"=>"mov_importo_avere",
"Categoria"=>"mov_fk_categoria", "Categoria"=>"mov_fk_categoria",
"Tag"=>"mov_fk_tags", "Tag"=>"mov_fk_tags",
"Conto"=>"conto_id", "Conto prelievo"=>"conto_id_da",
"Conto versamento"=>"conto_id_a",
]; ];
} }
@ -361,6 +376,12 @@ JOIN categories as c ON a.mov_fk_categoria=c.id';
} }
public static function getSuggestedCategory($descrizione)
{
$rule = ImportRule::whereRaw('? LIKE CONCAT("%", pattern, "%")', [$descrizione])->first();
return $rule ? $rule->category_id : null;
}

View File

@ -387,6 +387,11 @@ return [
'text' => 'Importa Generic CSV', 'text' => 'Importa Generic CSV',
'route' => 'importGen', 'route' => 'importGen',
], ],
[
'text' => 'Regole importazione',
'route' => 'import_rules.index',
// 'can' => ['import_rules'],
],
], ],
], ],

View File

@ -20,12 +20,14 @@ class CreateMovimentisTable extends Migration
$table->unsignedBigInteger('mov_fk_categoria'); $table->unsignedBigInteger('mov_fk_categoria');
$table->foreign('mov_fk_categoria')->references('id')->on('categories'); $table->foreign('mov_fk_categoria')->references('id')->on('categories');
$table->longText('mov_descrizione'); $table->longText('mov_descrizione');
$table->decimal('mov_importo',8,2); $table->decimal('mov_importo_dare',8,2);
$table->decimal('mov_importo_avere',8,2);
$table->unsignedBigInteger('mov_inserito_da'); $table->unsignedBigInteger('mov_inserito_da');
$table->foreign('mov_inserito_da')->references('id')->on('users'); $table->foreign('mov_inserito_da')->references('id')->on('users');
$table->unsignedBigInteger('mov_fk_tags'); $table->unsignedBigInteger('mov_fk_tags');
$table->foreign('mov_fk_tags')->references('id')->on('tags'); $table->foreign('mov_fk_tags')->references('id')->on('tags');
$table->foreignId('conto_id')->constrained('contos'); $table->foreignId('conto_id_da')->constrained('contos')->nullable();
$table->foreignId('conto_id_a')->constrained('contos')->nullable();
}); });
} }

View File

@ -14,6 +14,13 @@ return new class extends Migration
Schema::create('import_rules', function (Blueprint $table) { Schema::create('import_rules', function (Blueprint $table) {
$table->id(); $table->id();
$table->timestamps(); $table->timestamps();
$table->string('pattern');
$table->unsignedBigInteger('category_id');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
// $table->unique(['pattern', 'category_id'], 'unique_import_rule');
$table->string('description')->nullable(); // Optional description for the rule
$table->boolean('is_active')->default(true); // Flag to enable/disable the rule
$table->string('created_by')->nullable(); // User who created the rule
}); });
} }

View File

@ -7,17 +7,21 @@
@section('content') @section('content')
<form action="{{ route('conti.map.store') }}" method="POST"> <form action="{{ route('conti.map.store') }}" method="POST">
@csrf @csrf
@foreach ($csv as $header) @foreach ($db as $header=>$table)
<label>{{ $header }}</label> <div class="row">
<select name="mapping[{{ $header }}]"> <div class="col-md-3">
<label>{{ $header }}</label>
</div>
<div class="col-md-6">
<select name="mapping[{{ $table }}]">
<option value="">--Nessuno o Selezionare una colonna--</option> <option value="">--Nessuno o Selezionare una colonna--</option>
<option value="mov_data">Data Movimento</option> @foreach($csv as $csv_header)
<option value="mov_desc">Descrizione</option> <option value="{{ $csv_header }}">{{ $csv_header }}</option>
<option value="mov_importo">Importo</option> @endforeach
<option value="mov_fk_categoria">ID Categoria</option>
<option value="mov_fk_tag">ID Tag</option>
<option value="mov_fk_conto">ID Conto</option>
</select> </select>
</div>
</div>
@endforeach @endforeach
<input type="hidden" name="filename" value="{{ $filename .".csv" }}"> <input type="hidden" name="filename" value="{{ $filename .".csv" }}">
<button type="submit">Salva</button> <button type="submit">Salva</button>

View File

@ -34,7 +34,8 @@
<th>Categoria</th> <th>Categoria</th>
<th>Conto</th> <th>Conto</th>
<th>Descrizione</th> <th>Descrizione</th>
<th>Importo</th> <th>Importo Dare</th>
<th>Importo Avere</th>
<th>Azione</th> <th>Azione</th>
</tr> </tr>
</thead> </thead>
@ -46,7 +47,8 @@
<td>{{ $movimento->cat_name }}</td> <td>{{ $movimento->cat_name }}</td>
<td>{{ $movimento->nomeConto }}</td> <td>{{ $movimento->nomeConto }}</td>
<td>{{ $movimento->mov_descrizione }}</td> <td>{{ $movimento->mov_descrizione }}</td>
<td>&euro; {{ $movimento->mov_importo }}</td> <td>&euro; {{ $movimento->mov_importo_dare }}</td>
<td>&euro; {{ $movimento->mov_importo_avere }}</td>
<td> <td>
<button class="btn btn-warning btn-detail open_modal_modifica" value="{{ $movimento->id }}"><i class="fa-solid fa-pencil"></i></button>&nbsp; <button class="btn btn-warning btn-detail open_modal_modifica" value="{{ $movimento->id }}"><i class="fa-solid fa-pencil"></i></button>&nbsp;
<a class="btn btn-danger" href="/admin/movimenti/delete?id={{ $movimento->id }}"><i class="fa-solid fa-trash-can"></i></a>&nbsp; <a class="btn btn-danger" href="/admin/movimenti/delete?id={{ $movimento->id }}"><i class="fa-solid fa-trash-can"></i></a>&nbsp;

View File

@ -0,0 +1,46 @@
@extends('adminlte::page')
@section('content_header')
<h1>Crea una regola di importazione</h1>
@stop
@section('content')
<div class="container">
<p>Compila il modulo per creare una nuova regola di importazione.</p>
<div class="card">
<div class="card-header">
<h3 class="card-title">Nuova Regola di Importazione</h3>
</div>
<div class="card-body">
<form action="{{ route('import_rules.store') }}" method="POST">
@csrf
<div class="form-group">
<label for="pattern">Pattern</label>
<input type="text" name="pattern" id="pattern" class="form-control" required>
</div>
<div class="form-group">
<label for="category_id">Categoria</label>
<select name="category_id" id="category_id" class="form-control" required>
<option value="">Seleziona una categoria</option>
@foreach($categorie as $category)
<option value="{{ $category->id }}">{{ $category->cat_name }}</option>
@endforeach
</select>
<div class="form-group">
<label for="description">Descrizione</label>
<textarea name="description" id="description" class="form-control" rows="3" required></textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Crea Regola</button>
<a href="{{ route('import_rules.index') }}" class="btn btn-secondary">Annulla</a>
</div>
</form>
</div>
<div class="card-footer">
<a href="{{ route('import_rules.index') }}" class="btn btn-secondary">Torna alla lista</a>
</div>
</div>
</div>
@endsection

View File

@ -0,0 +1,49 @@
@extends('adminlte::page')
@section('content_header')
<h1>Regole di importazione e assegnazione delle categorie</h1>
@endsection
@section('content')
<div class="container">
<p>Qui puoi gestire le regole di importazione e assegnazione delle categorie.</p>
<div class="card">
<div class="card-header">
<h3 class="card-title">Regole di Importazione</h3>
</div>
<div class="card-body">
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Pattern</th>
<th>Descrizione</th>
<th>Azioni</th>
</tr>
</thead>
<tbody>
@foreach($rules as $rule)
<tr>
<td>{{ $rule->id }}</td>
<td>{{ $rule->pattern }}</td>
<td>{{ $rule->description }}</td>
<td>
<a href="{{ route('import_rules.edit', $rule->id) }}" class="btn btn-primary btn-sm">Modifica</a>
<form action="{{ route('import_rules.destroy', $rule->id) }}" method="POST" style="display:inline;">
@csrf
@method('DELETE')
<button type="submit" class="btn btn-danger btn-sm">Elimina</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="card-footer">
<a href="{{ route('import_rules.create') }}" class="btn btn-success">Aggiungi Nuova Regola</a>
</div>
</div>
</div>
@endsection

View File

@ -26,6 +26,7 @@ use App\Http\Controllers\ContrattiController;
use App\Http\Controllers\TodolistController; use App\Http\Controllers\TodolistController;
use App\Http\Controllers\ContoController; use App\Http\Controllers\ContoController;
use App\Http\Controllers\GenDocController; use App\Http\Controllers\GenDocController;
use App\Http\Controllers\ImportRuleController;
use App\Mail\myTestEmail; use App\Mail\myTestEmail;
// API // API
@ -100,6 +101,9 @@ Route::middleware([
Route::get('/admin/movimenti/giroconto', [MovimentiController::class,'giroconto'])->name('giroconto'); Route::get('/admin/movimenti/giroconto', [MovimentiController::class,'giroconto'])->name('giroconto');
Route::post('/admin/movimenti/giroconto', [MovimentiController::class,'girocontoPost']); Route::post('/admin/movimenti/giroconto', [MovimentiController::class,'girocontoPost']);
Route::get('/admin/movimenti/import_rules', [ImportRuleController::class, 'index'])->name('import_rules.index');
Route::get('/admin/movimenti/import_rules/create', [ImportRuleController::class, 'create'])->name('import_rules.create');
Route::post('/admin/movimenti/import_rules', [ImportRuleController::class, 'store'])->name('import_rules.store');
Route::resource('admin/conti', ContoController::class); Route::resource('admin/conti', ContoController::class);