From 0169ec6acdfffd356c84699cd602d023d755e3ee Mon Sep 17 00:00:00 2001 From: Flavio Barachino Date: Tue, 5 Aug 2025 17:40:13 +0200 Subject: [PATCH 01/11] effettuato modifiche per mappatura campi [BUG] non trova il file --- app/Http/Controllers/MovimentiController.php | 23 +++++++++++++ app/Models/Movimenti.php | 34 +++++++++++++------ config/adminlte.php | 5 +++ resources/views/conti/importGen.blade.php | 27 +++++++++++++++ resources/views/conti/importGeneric.blade.php | 25 ++++++++++++++ routes/web.php | 5 ++- 6 files changed, 108 insertions(+), 11 deletions(-) create mode 100644 resources/views/conti/importGen.blade.php create mode 100644 resources/views/conti/importGeneric.blade.php diff --git a/app/Http/Controllers/MovimentiController.php b/app/Http/Controllers/MovimentiController.php index 28d2819..0dee858 100644 --- a/app/Http/Controllers/MovimentiController.php +++ b/app/Http/Controllers/MovimentiController.php @@ -335,6 +335,22 @@ class MovimentiController extends Controller } } + public function importGenericCsv(Request $request) + { + if ($request->hasFile('filename')) + { + $filename=$request->file('filename')->store(); + $csv_headers=Movimenti::retrieveHeaders($filename); + $db_fields=Movimenti::getDbFields(); + + return view('conti.importGeneric',['csv'=>$csv_headers,'db'=>$db_fields,'filename'=>$filename]); + } + + else { + return 'Nessun File trovato'; + } + } + public function importFile() { return view('conti.import'); @@ -345,6 +361,13 @@ class MovimentiController extends Controller return view('conti.importCR'); } + public function importFileGen() + { + return view('conti.importGen'); + } + + + /* public function test() { Movimenti::getYearsFromMovimenti(); diff --git a/app/Models/Movimenti.php b/app/Models/Movimenti.php index 2a43767..f95bc43 100644 --- a/app/Models/Movimenti.php +++ b/app/Models/Movimenti.php @@ -5,10 +5,12 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Storage; use Rap2hpoutre\FastExcel\FastExcel; use App\Models\Categorie; use App\Models\Conto; use App\Models\User; +//use Illuminate\Support\Facades\Schema; class Movimenti extends Model { @@ -45,7 +47,7 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; public function Tags() { - return $this->belongsTo(Tags::class); + return $this->belongsTo(tag::class); } public static function getList() { @@ -242,7 +244,7 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; public static function importEstrattoIng($filename) { - $inputPath='/var/www/html/gestionale_mt/public/storage/tenant'.tenant('id').'/'.$filename; + $inputPath='/var/www/html/gestionale2025/storage/app/public/'.$filename; // $outputPath='/var/www/html/gestionale_mt/public/tenant'.tenant('id').'/import/'.$filename.'.csv'; $outputPath = $inputPath.'.csv'; rename($inputPath,$outputPath); @@ -275,7 +277,7 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; public static function importEstrattoCR($filename) { - $inputPath='/var/www/html/gestionale_mt/public/storage/tenant'.tenant('id').'/'.$filename; + $inputPath='/var/www/html/gestionale2025/storage/app/public/'.$filename; // $outputPath='/var/www/html/gestionale_mt/public/'.tenant('id')."/app/".$filename; $outputPath = $inputPath.'.csv'; rename($inputPath,$outputPath); @@ -317,15 +319,27 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; } // Test filtri categoria - public function mapFieldByName($name) + public static function retrieveHeaders($filename) { - // definisce lo schema per rigenerare il file CSV secondo standard di importazione - $fields = Illuminate\Support\Facade\Schema::getColumnListing('movimentis')->mapFieldByName; - foreach ($fields as $field) - { - echo $column . "\n"; - } + $inputPath= Storage::path($filename); + $outputPath = $inputPath.'.csv'; + rename($inputPath,$outputPath); + $rows = (new FastExcel)->configureCsv(';')->import($outputPath); + $headers = array_keys($rows->first()); + return $headers; + } + + public static function getDbFields() + { + return [ + "Data movimento"=>"mov_data", + "Descrizione"=>"mov_descrizione", + "Importo"=>"mov_importo", + "Categoria"=>"mov_fk_categoria", + "Tag"=>"mov_fk_tags", + "Conto"=>"conto_id", + ]; } // Test applicazione regole diff --git a/config/adminlte.php b/config/adminlte.php index 27f2416..7c476a1 100644 --- a/config/adminlte.php +++ b/config/adminlte.php @@ -383,6 +383,11 @@ return [ 'text' => 'Importa Estratto conto Cassa Rurale', 'route' => 'importCR', ], + [ + 'text' => 'Importa Generic CSV', + 'route' => 'importGen', + ], + ], ], ], diff --git a/resources/views/conti/importGen.blade.php b/resources/views/conti/importGen.blade.php new file mode 100644 index 0000000..8c46167 --- /dev/null +++ b/resources/views/conti/importGen.blade.php @@ -0,0 +1,27 @@ +@extends('adminlte::page') + +@section('content_header') +

Importazione Estratto conto Generico

+@endsection + +@section('content') + +
+ +
+
+
+ @csrf +
+ + +
+
+ +
+
+
+
+
+ + @endsection diff --git a/resources/views/conti/importGeneric.blade.php b/resources/views/conti/importGeneric.blade.php new file mode 100644 index 0000000..1d072c6 --- /dev/null +++ b/resources/views/conti/importGeneric.blade.php @@ -0,0 +1,25 @@ +@extends('adminlte::page') + +@section('content_header') +

Mappa i campi

+@endsection + +@section('content') +
+@csrf + @foreach ($csv as $header) + + + @endforeach + + +
+@endsection diff --git a/routes/web.php b/routes/web.php index 56603e4..b5de6ac 100644 --- a/routes/web.php +++ b/routes/web.php @@ -94,6 +94,8 @@ Route::middleware([ Route::post('admin/movimenti/import', [MovimentiController::class,'importEC_ING']); Route::get('admin/movimenti/importcr', [MovimentiController::class,'importFileCR'])->name('importCR'); Route::post('admin/movimenti/importcr', [MovimentiController::class,'importEC_CR']); + Route::get('admin/movimenti/importgen', [MovimentiController::class,'importFileGen'])->name('importGen'); + Route::post('admin/movimenti/importgen', [MovimentiController::class,'importGenericCsv']); Route::get('/admin/movimenti/giroconto', [MovimentiController::class,'giroconto'])->name('giroconto'); Route::post('/admin/movimenti/giroconto', [MovimentiController::class,'girocontoPost']); @@ -262,5 +264,6 @@ Route::middleware('auth:sanctum')->group(function () { Route::delete('/api/conti/{id}', [ApiContoController::class, 'deleteConto']); + }); }); -}); + From 0ca16a6969582642eed04b202e93e3d5c2897e46 Mon Sep 17 00:00:00 2001 From: Flavio Barachino Date: Tue, 5 Aug 2025 18:13:22 +0200 Subject: [PATCH 02/11] corretto problema precedente. [DEBUG] del post degli headers --- app/Http/Controllers/MovimentiController.php | 6 ++++++ resources/views/conti/importGeneric.blade.php | 4 ++-- routes/web.php | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/MovimentiController.php b/app/Http/Controllers/MovimentiController.php index 0dee858..0b2fdc6 100644 --- a/app/Http/Controllers/MovimentiController.php +++ b/app/Http/Controllers/MovimentiController.php @@ -351,6 +351,12 @@ class MovimentiController extends Controller } } + public function importmappedCsv(Request $request) + { + //$request->mov_data + dd($request); + } + public function importFile() { return view('conti.import'); diff --git a/resources/views/conti/importGeneric.blade.php b/resources/views/conti/importGeneric.blade.php index 1d072c6..0736bd6 100644 --- a/resources/views/conti/importGeneric.blade.php +++ b/resources/views/conti/importGeneric.blade.php @@ -5,7 +5,7 @@ @endsection @section('content') -
+ @csrf @foreach ($csv as $header) @@ -19,7 +19,7 @@ @endforeach - +
@endsection diff --git a/routes/web.php b/routes/web.php index b5de6ac..ae2219e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -96,6 +96,7 @@ Route::middleware([ Route::post('admin/movimenti/importcr', [MovimentiController::class,'importEC_CR']); Route::get('admin/movimenti/importgen', [MovimentiController::class,'importFileGen'])->name('importGen'); Route::post('admin/movimenti/importgen', [MovimentiController::class,'importGenericCsv']); + Route::post('admin/movimenti/importmapped', [MovimentiController::class,'importmappedCsv'])->name('conti.map.store'); Route::get('/admin/movimenti/giroconto', [MovimentiController::class,'giroconto'])->name('giroconto'); Route::post('/admin/movimenti/giroconto', [MovimentiController::class,'girocontoPost']); From a1742e4e61cc585c1e367301f1670a4c1c7d154f Mon Sep 17 00:00:00 2001 From: Flavio Barachino Date: Tue, 5 Aug 2025 21:03:39 +0200 Subject: [PATCH 03/11] modifica a mimportmappedCsv --- app/Http/Controllers/MovimentiController.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/Http/Controllers/MovimentiController.php b/app/Http/Controllers/MovimentiController.php index 0b2fdc6..23bbe5f 100644 --- a/app/Http/Controllers/MovimentiController.php +++ b/app/Http/Controllers/MovimentiController.php @@ -354,6 +354,20 @@ class MovimentiController extends Controller public function importmappedCsv(Request $request) { //$request->mov_data + foreach($request->mapped as $key => $value) + { + + if($value!=null) + { + $map=array( + $csv_field=$key, + $db_field=$value, + ); + dd($map); + } + + $mappdCvs=(new FastExcel)->configureCsv(';')->create($request->filename .".new.csv",); + } dd($request); } From 652f9a7e767fbdeb90e8e39477a00a55db06cb42 Mon Sep 17 00:00:00 2001 From: Flavio Barachino Date: Wed, 6 Aug 2025 19:28:01 +0200 Subject: [PATCH 04/11] Aggiunto mappatura e prototipo filtro --- app/Http/Controllers/ImportRuleController.php | 17 +++++++ app/Http/Controllers/MovimentiController.php | 49 ++++++++++++++----- app/Models/ImportRule.php | 4 ++ app/Models/Movimenti.php | 29 +++++++++-- config/adminlte.php | 5 ++ ...2_02_04_134245_create_movimentis_table.php | 6 ++- ...08_05_071946_create_import_rules_table.php | 7 +++ resources/views/conti/importGeneric.blade.php | 22 +++++---- .../views/conti/movimenti/list.blade.php | 6 ++- resources/views/import_rules/create.blade.php | 46 +++++++++++++++++ resources/views/import_rules/index.blade.php | 49 +++++++++++++++++++ routes/web.php | 4 ++ 12 files changed, 215 insertions(+), 29 deletions(-) create mode 100644 resources/views/import_rules/create.blade.php create mode 100644 resources/views/import_rules/index.blade.php diff --git a/app/Http/Controllers/ImportRuleController.php b/app/Http/Controllers/ImportRuleController.php index 53f9525..a8830ee 100644 --- a/app/Http/Controllers/ImportRuleController.php +++ b/app/Http/Controllers/ImportRuleController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Models\Categorie; use App\Models\ImportRule; use Illuminate\Http\Request; @@ -13,6 +14,8 @@ class ImportRuleController extends Controller public function index() { // + $rules = ImportRule::all(); + return view('import_rules.index', compact('rules')); } /** @@ -21,6 +24,11 @@ class ImportRuleController extends Controller 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) { // + $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 } /** diff --git a/app/Http/Controllers/MovimentiController.php b/app/Http/Controllers/MovimentiController.php index 23bbe5f..b05486f 100644 --- a/app/Http/Controllers/MovimentiController.php +++ b/app/Http/Controllers/MovimentiController.php @@ -13,9 +13,14 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Auth; use Rap2hpoutre\FastExcel\FastExcel; +use Illuminate\Support\Facades\Storage; +use DateTime; + class MovimentiController extends Controller { + public $map; + // Gestione dei movimenti public static function newMovimenti() { $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) { //$request->mov_data - foreach($request->mapped as $key => $value) + $mapped=$request['mapping']; + foreach( $mapped as $key => $value) { - if($value!=null) - { - $map=array( - $csv_field=$key, - $db_field=$value, - ); - dd($map); - } - - $mappdCvs=(new FastExcel)->configureCsv(';')->create($request->filename .".new.csv",); + { + $this->map[$key]=$value; + $collection = collect($this->map); + } } - 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() diff --git a/app/Models/ImportRule.php b/app/Models/ImportRule.php index 0f04a2b..e29c640 100644 --- a/app/Models/ImportRule.php +++ b/app/Models/ImportRule.php @@ -8,4 +8,8 @@ use Illuminate\Database\Eloquent\Model; class ImportRule extends Model { use HasFactory; + + +// In MovimentiController o direttamente nel model Movimenti + } diff --git a/app/Models/Movimenti.php b/app/Models/Movimenti.php index f95bc43..d2be652 100644 --- a/app/Models/Movimenti.php +++ b/app/Models/Movimenti.php @@ -18,6 +18,18 @@ class Movimenti extends Model protected $dates = ['mov_data']; 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 a.id, a.mov_data, @@ -57,7 +69,8 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; 'SELECT a.id, a.mov_data, - a.mov_importo, + a.mov_importo_dare, + a.mov_importo_avere, a.mov_descrizione, c.cat_name, t.tag_name, @@ -66,7 +79,7 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; FROM movimentis as a JOIN tags as t ON a.mov_fk_tags=t.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()); @@ -335,10 +348,12 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; return [ "Data movimento"=>"mov_data", "Descrizione"=>"mov_descrizione", - "Importo"=>"mov_importo", + "Importo Dare"=>"mov_importo_dare", + "Importo Avere"=>"mov_importo_avere", "Categoria"=>"mov_fk_categoria", "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; + } + diff --git a/config/adminlte.php b/config/adminlte.php index 7c476a1..7a8a6d3 100644 --- a/config/adminlte.php +++ b/config/adminlte.php @@ -387,6 +387,11 @@ return [ 'text' => 'Importa Generic CSV', 'route' => 'importGen', ], + [ + 'text' => 'Regole importazione', + 'route' => 'import_rules.index', + // 'can' => ['import_rules'], + ], ], ], diff --git a/database/migrations/2022_02_04_134245_create_movimentis_table.php b/database/migrations/2022_02_04_134245_create_movimentis_table.php index 5954ae3..b6f4a0f 100644 --- a/database/migrations/2022_02_04_134245_create_movimentis_table.php +++ b/database/migrations/2022_02_04_134245_create_movimentis_table.php @@ -20,12 +20,14 @@ class CreateMovimentisTable extends Migration $table->unsignedBigInteger('mov_fk_categoria'); $table->foreign('mov_fk_categoria')->references('id')->on('categories'); $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->foreign('mov_inserito_da')->references('id')->on('users'); $table->unsignedBigInteger('mov_fk_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(); }); } diff --git a/database/migrations/2025_08_05_071946_create_import_rules_table.php b/database/migrations/2025_08_05_071946_create_import_rules_table.php index 3717306..e2d0ff5 100644 --- a/database/migrations/2025_08_05_071946_create_import_rules_table.php +++ b/database/migrations/2025_08_05_071946_create_import_rules_table.php @@ -14,6 +14,13 @@ return new class extends Migration Schema::create('import_rules', function (Blueprint $table) { $table->id(); $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 }); } diff --git a/resources/views/conti/importGeneric.blade.php b/resources/views/conti/importGeneric.blade.php index 0736bd6..230b06e 100644 --- a/resources/views/conti/importGeneric.blade.php +++ b/resources/views/conti/importGeneric.blade.php @@ -7,17 +7,21 @@ @section('content')
@csrf - @foreach ($csv as $header) - - - - - - - - + @foreach($csv as $csv_header) + + @endforeach + + + @endforeach diff --git a/resources/views/conti/movimenti/list.blade.php b/resources/views/conti/movimenti/list.blade.php index c011036..59380b1 100644 --- a/resources/views/conti/movimenti/list.blade.php +++ b/resources/views/conti/movimenti/list.blade.php @@ -34,7 +34,8 @@ Categoria Conto Descrizione - Importo + Importo Dare + Importo Avere Azione @@ -46,7 +47,8 @@ {{ $movimento->cat_name }} {{ $movimento->nomeConto }} {{ $movimento->mov_descrizione }} - € {{ $movimento->mov_importo }} + € {{ $movimento->mov_importo_dare }} + € {{ $movimento->mov_importo_avere }}     diff --git a/resources/views/import_rules/create.blade.php b/resources/views/import_rules/create.blade.php new file mode 100644 index 0000000..1564530 --- /dev/null +++ b/resources/views/import_rules/create.blade.php @@ -0,0 +1,46 @@ +@extends('adminlte::page') + +@section('content_header') +

Crea una regola di importazione

+@stop + +@section('content') +
+

Compila il modulo per creare una nuova regola di importazione.

+ +
+
+

Nuova Regola di Importazione

+
+
+ + @csrf +
+ + +
+
+ + +
+ + +
+
+ + Annulla +
+ +
+ + +
+
+@endsection diff --git a/resources/views/import_rules/index.blade.php b/resources/views/import_rules/index.blade.php new file mode 100644 index 0000000..cd22df8 --- /dev/null +++ b/resources/views/import_rules/index.blade.php @@ -0,0 +1,49 @@ +@extends('adminlte::page') + +@section('content_header') +

Regole di importazione e assegnazione delle categorie

+@endsection + +@section('content') +
+

Qui puoi gestire le regole di importazione e assegnazione delle categorie.

+ +
+
+

Regole di Importazione

+
+
+ + + + + + + + + + + @foreach($rules as $rule) + + + + + + + @endforeach + +
IDPatternDescrizioneAzioni
{{ $rule->id }}{{ $rule->pattern }}{{ $rule->description }} + Modifica +
+ @csrf + @method('DELETE') + +
+
+
+ +
+
+@endsection diff --git a/routes/web.php b/routes/web.php index ae2219e..5763da6 100644 --- a/routes/web.php +++ b/routes/web.php @@ -26,6 +26,7 @@ use App\Http\Controllers\ContrattiController; use App\Http\Controllers\TodolistController; use App\Http\Controllers\ContoController; use App\Http\Controllers\GenDocController; +use App\Http\Controllers\ImportRuleController; use App\Mail\myTestEmail; // API @@ -100,6 +101,9 @@ Route::middleware([ Route::get('/admin/movimenti/giroconto', [MovimentiController::class,'giroconto'])->name('giroconto'); 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); From f82f65a0c5d700f662bd065230de51b7905fdf82 Mon Sep 17 00:00:00 2001 From: Flavio Barachino Date: Thu, 7 Aug 2025 08:26:43 +0200 Subject: [PATCH 05/11] Creato funzione di filtraggio e assegnazione categoria in importazione in base alle regole di assegnazione --- app/Http/Controllers/ImportRuleController.php | 10 +++++++++- app/Http/Controllers/MovimentiController.php | 2 +- app/Models/ImportRule.php | 8 +++++++- app/Models/Movimenti.php | 16 ++++++++++++++- database/seeders/CategorieSeeder.php | 20 ++++++++++++++++--- routes/web.php | 12 +++++++++-- 6 files changed, 59 insertions(+), 9 deletions(-) diff --git a/app/Http/Controllers/ImportRuleController.php b/app/Http/Controllers/ImportRuleController.php index a8830ee..b6eac23 100644 --- a/app/Http/Controllers/ImportRuleController.php +++ b/app/Http/Controllers/ImportRuleController.php @@ -44,7 +44,15 @@ class ImportRuleController extends Controller 'is_active' => 'boolean', 'created_by' => 'nullable|string|max:255', ]); - ImportRule::create($request->all()); + ImportRule::create( + [ + 'category_id'=>$request->category_id, + 'pattern'=>$request->pattern, + 'description'=>$request->description, + 'is_active'=>1, + ] + + ); return redirect()->route('import_rules.index'); // Redirect to the index after storing the rule } diff --git a/app/Http/Controllers/MovimentiController.php b/app/Http/Controllers/MovimentiController.php index b05486f..d00a44e 100644 --- a/app/Http/Controllers/MovimentiController.php +++ b/app/Http/Controllers/MovimentiController.php @@ -381,7 +381,7 @@ class MovimentiController extends Controller '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_categoria' => Movimenti::setCategoriesFromCsv($line[$this->map['mov_descrizione']]), 'mov_fk_tags' => 1, 'mov_inserito_da' => Auth::id(), 'conto_id_da' => 1 diff --git a/app/Models/ImportRule.php b/app/Models/ImportRule.php index e29c640..e83c528 100644 --- a/app/Models/ImportRule.php +++ b/app/Models/ImportRule.php @@ -8,7 +8,13 @@ use Illuminate\Database\Eloquent\Model; class ImportRule extends Model { use HasFactory; - + protected $fillable = [ + 'category_id', + 'pattern', + 'description', + 'is_active', + 'created_by', + ]; // In MovimentiController o direttamente nel model Movimenti diff --git a/app/Models/Movimenti.php b/app/Models/Movimenti.php index d2be652..4e691c2 100644 --- a/app/Models/Movimenti.php +++ b/app/Models/Movimenti.php @@ -379,9 +379,23 @@ 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; + return $rule ? $rule->category_id : 1; } + public static function setCategoriesFromCsv($descrizione) + { + $rules = \App\Models\ImportRule::all(); + $categoria = 1; // Default category + + foreach ($rules as $rule) { + if (preg_match("/$rule->pattern/i", $descrizione)) { + $categoria = $rule->category_id; + break; + } + } + + return $categoria; + } diff --git a/database/seeders/CategorieSeeder.php b/database/seeders/CategorieSeeder.php index 049cd6a..61f6afc 100644 --- a/database/seeders/CategorieSeeder.php +++ b/database/seeders/CategorieSeeder.php @@ -17,9 +17,9 @@ class CategorieSeeder extends Seeder // Inserisce le categorie necessarie DB::table('categories')->insert( [ - 'cat_name'=>'Automobili', + 'cat_name'=>'Da Selezionare', 'cat_uscita'=>1, - 'cat_entrata'=>0, + 'cat_entrata'=>1, ] ); DB::table('categories')->insert( @@ -30,9 +30,23 @@ class CategorieSeeder extends Seeder ); DB::table('categories')->insert( [ - 'cat_name'=>'Utenze', + 'cat_name'=>'Automobili', 'cat_uscita'=>1, 'cat_entrata'=>0] ); + DB::table('categories')->insert( + [ + 'cat_name'=>'Alimentari', + 'cat_uscita'=>1, + 'cat_entrata'=>0, + ] + ); + DB::table('categories')->insert( + [ + 'cat_name'=>'Utenze', + 'cat_uscita'=>1, + 'cat_entrata'=>0, + ] + ); } } diff --git a/routes/web.php b/routes/web.php index 5763da6..66b9339 100644 --- a/routes/web.php +++ b/routes/web.php @@ -98,15 +98,23 @@ Route::middleware([ Route::get('admin/movimenti/importgen', [MovimentiController::class,'importFileGen'])->name('importGen'); Route::post('admin/movimenti/importgen', [MovimentiController::class,'importGenericCsv']); Route::post('admin/movimenti/importmapped', [MovimentiController::class,'importmappedCsv'])->name('conti.map.store'); - Route::get('/admin/movimenti/giroconto', [MovimentiController::class,'giroconto'])->name('giroconto'); - 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::get('/admin/movimenti/import_rules/{import_rule}', [ImportRuleController::class, 'show'])->name('import_rules.show'); + Route::get('/admin/movimenti/import_rules/{import_rule}/edit', [ImportRuleController::class, 'edit'])->name('import_rules.edit'); + Route::put('/admin/movimenti/import_rules/{import_rule}', [ImportRuleController::class, 'update'])->name('import_rules.update'); + Route::delete('/admin/movimenti/import_rules/{import_rule}', [ImportRuleController::class, 'destroy'])->name('import_rules.destroy'); + + Route::resource('admin/conti', ContoController::class); + Route::get('/admin/movimenti/giroconto', [MovimentiController::class,'giroconto'])->name('giroconto'); + Route::post('/admin/movimenti/giroconto', [MovimentiController::class,'girocontoPost']); + // CATEGORIE Route::get('admin/categorie', [CategorieController::class,'listCategorie'])->name('categorie'); Route::post('admin/categorie', [CategorieController::class,'insCategorie']); From 9320ce76a1564b5db68d79d8cca591b6ea9bfe33 Mon Sep 17 00:00:00 2001 From: Flavio Barachino Date: Thu, 7 Aug 2025 16:10:49 +0200 Subject: [PATCH 06/11] sistemato alcuni riferimenti ad importo e modifica per sole spese. Vedere anche per entrate --- app/Http/Controllers/MovimentiController.php | 86 ++++++++++++------- app/Models/Movimenti.php | 74 ++++++++-------- config/logging.php | 8 ++ ...2_02_04_134245_create_movimentis_table.php | 4 +- public/js/app/movimenti.js | 5 +- .../views/conti/movimenti/list.blade.php | 19 ++-- 6 files changed, 112 insertions(+), 84 deletions(-) diff --git a/app/Http/Controllers/MovimentiController.php b/app/Http/Controllers/MovimentiController.php index d00a44e..c8583a7 100644 --- a/app/Http/Controllers/MovimentiController.php +++ b/app/Http/Controllers/MovimentiController.php @@ -349,7 +349,7 @@ class MovimentiController extends Controller $db_fields=Movimenti::getDbFields(); return view('conti.importGeneric',['csv'=>$csv_headers,'db'=>$db_fields,'filename'=>$filename]); - } + } else { return 'Nessun File trovato'; @@ -358,42 +358,63 @@ class MovimentiController extends Controller public function importmappedCsv(Request $request) { - //$request->mov_data - $mapped=$request['mapping']; - foreach( $mapped as $key => $value) - { - if($value!=null) - { - $this->map[$key]=$value; - $collection = collect($this->map); + $this->prepareMapping($request['mapping']); + $filename = Storage::path($request->filename); + + (new FastExcel)->configureCsv(';')->import($filename, function($line) { + $data = $this->mapCsvLineToDb($line); + // dd($data); + if (isset($data['mov_data'])) { + Movimenti::create($data); + } + }); + + return redirect(Route('movimenti')); + } + + /** + * Prepara la mappatura tra i campi CSV e i campi DB + */ + private function prepareMapping($mapping) + { + foreach ($mapping as $key => $value) { + if ($value != null) { + $this->map[$key] = $value; } } - //dd ($this->map,$collection); + } - $mappdCvs=(new FastExcel)->configureCsv(';')->import( - Storage::path($request->filename), function($line){ - if(isset($line[$this->map['mov_data']])) - { + /** + * Mappa una riga del CSV ai campi del database + */ + private function mapCsvLineToDb($line) + { + if (isset($line[$this->map['mov_data']])) { + $data = [ + 'mov_data' => $this->parseDate($line[$this->map['mov_data']]), + 'mov_descrizione' => $line[$this->map['mov_descrizione']] ?? null, + 'mov_importo_dare' => Movimenti::cleanImporto($line[$this->map['mov_importo_dare']]?? null) , + 'mov_importo_avere' => Movimenti::cleanImporto($line[$this->map['mov_importo_avere']] ?? null), + 'mov_fk_categoria' => Movimenti::setCategoriesFromCsv($line[$this->map['mov_descrizione']] ?? ''), + 'mov_fk_tags' => 1, + 'mov_inserito_da' => Auth::id(), + 'conto_id_da' => 1, + 'conto_id_a' => 1, + ]; + return $data; + } + return null; // Se non c'è la data, non importa la riga - 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' => Movimenti::setCategoriesFromCsv($line[$this->map['mov_descrizione']]), - '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')); + } + + /** + * Converte la data dal formato d/m/Y a Y-m-d + */ + private function parseDate($dateString) + { + $date = DateTime::createFromFormat('d/m/Y', $dateString); + return $date ? $date->format('Y-m-d') : null; } public function importFile() @@ -428,4 +449,5 @@ class MovimentiController extends Controller $mov=Movimenti::getMovimentoById($id); return json_encode($mov); } + } diff --git a/app/Models/Movimenti.php b/app/Models/Movimenti.php index 4e691c2..d4c691e 100644 --- a/app/Models/Movimenti.php +++ b/app/Models/Movimenti.php @@ -10,7 +10,8 @@ use Rap2hpoutre\FastExcel\FastExcel; use App\Models\Categorie; use App\Models\Conto; use App\Models\User; -//use Illuminate\Support\Facades\Schema; +use App\Models\ImportRule; + class Movimenti extends Model { @@ -33,7 +34,8 @@ class Movimenti extends Model public static $query= 'SELECT a.id, a.mov_data, - a.mov_importo, + a.mov_importo_dare, + a.mov_importo_avere, a.mov_descrizione, c.cat_name, t.tag_name, @@ -186,7 +188,8 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; 'mov_data' => $request['mov_data'], 'mov_fk_categoria'=>$request['mov_fk_categoria'], 'mov_descrizione'=>$request['mov_descrizione'], - 'mov_importo'=>$request['mov_importo'], + 'mov_importo_dare' => $request['mov_importo_dare'], + 'mov_importo_avere' => $request['mov_importo_avere'], 'mov_fk_tags'=>$request['mov_fk_tags'], 'mov_inserito_da'=>$request['userid'], ]); @@ -203,7 +206,8 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; $expression= DB::raw('SELECT a.id, a.mov_data, - a.mov_importo, + a.mov_importo_dare, + a.mov_importo_avere, a.mov_descrizione, c.cat_name, t.tag_name, @@ -222,7 +226,8 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; $expression=DB::raw(' SELECT a.id, a.mov_data, - a.mov_importo, + a.mov_importo_dare, + a.mov_importo_avere, a.mov_descrizione, c.cat_name, t.tag_name, @@ -241,7 +246,8 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; $expression=DB::raw('SELECT a.id, a.mov_data, - a.mov_importo, + a.mov_importo_dare, + a.mov_importo_avere, a.mov_descrizione, c.cat_name, t.tag_name, @@ -357,25 +363,9 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; ]; } - // Test applicazione regole - public function setCategoriaMovimento($movimento) - { - $rules= \App\Models\ImportRule::all(); - foreach ($rules as $role) - { - if (preg_match("/$role->parola/i","$movimento->descrizione")) - { - $movimento->catemov_fk_categoria=$role->categoria_id; - } - else - { - $movimento->catemov_fk_categoria=1; - } - } - - } + // Ritorna la categoria suggerita in base alla descrizione del movimento da utilizzare sul db public static function getSuggestedCategory($descrizione) { $rule = ImportRule::whereRaw('? LIKE CONCAT("%", pattern, "%")', [$descrizione])->first(); @@ -384,7 +374,7 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; public static function setCategoriesFromCsv($descrizione) { - $rules = \App\Models\ImportRule::all(); + $rules = ImportRule::all(); $categoria = 1; // Default category foreach ($rules as $rule) { @@ -400,12 +390,13 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; - + // Ritorna gli anni presenti nei movimenti public static function getYearsFromMovimenti() { - $anni=DB::table('movimentis')->select(DB::raw('DISTINCT YEAR(mov_data) as anno'))->get(); - // dd($anni); // for test purposes - return $anni; + return self::selectRaw('YEAR(mov_data) as anno') + ->distinct() + ->orderBy('anno', 'desc') + ->get(); } @@ -424,24 +415,27 @@ JOIN categories as c ON a.mov_fk_categoria=c.id'; } } + // Ritorna la somma delle entrate per un anno specifico public static function getEntrate($year) { - $entrate_anno=DB::table('movimentis') - ->where('mov_importo','>',0) - ->whereYear('mov_data', '=' , $year) - ->sum('mov_importo'); - //->get(); - return $entrate_anno; + return self::whereYear('mov_data', $year) + ->sum('mov_importo_avere'); } + // Ritorna la somma delle uscite per un anno specifico public static function getUscite($year) { - $uscite_anno=DB::table('movimentis') - ->where('mov_importo','<',0) - ->whereYear('mov_data', '=' , $year) - ->sum('mov_importo'); - //->get(); - return ($uscite_anno); + return self::whereYear('mov_data', $year) + ->sum('mov_importo_dare'); + } + + public static function cleanImporto($importo){ + // Rimuove i punti e sostituisce la virgola con un punto + $importo = str_replace('.', '', $importo); + $importo = str_replace(',', '.', $importo); + $importo = str_replace('-', '', $importo); + $importo = str_replace('+', '', $importo); + return $importo; } } diff --git a/config/logging.php b/config/logging.php index d526b64..f078a43 100644 --- a/config/logging.php +++ b/config/logging.php @@ -65,6 +65,14 @@ return [ 'replace_placeholders' => true, ], + 'app' => [ + 'driver' => 'single', + 'path' => storage_path('logs/gestionale2025.log'), + 'level' => env('LOG_LEVEL', 'debug'), + 'days' => env('LOG_DAILY_DAYS', 14), + 'replace_placeholders' => true, + ], + 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), diff --git a/database/migrations/2022_02_04_134245_create_movimentis_table.php b/database/migrations/2022_02_04_134245_create_movimentis_table.php index b6f4a0f..ec86736 100644 --- a/database/migrations/2022_02_04_134245_create_movimentis_table.php +++ b/database/migrations/2022_02_04_134245_create_movimentis_table.php @@ -20,8 +20,8 @@ class CreateMovimentisTable extends Migration $table->unsignedBigInteger('mov_fk_categoria'); $table->foreign('mov_fk_categoria')->references('id')->on('categories'); $table->longText('mov_descrizione'); - $table->decimal('mov_importo_dare',8,2); - $table->decimal('mov_importo_avere',8,2); + $table->decimal('mov_importo_dare',8,2)->nullable(); + $table->decimal('mov_importo_avere',8,2)->nullable(); $table->unsignedBigInteger('mov_inserito_da'); $table->foreign('mov_inserito_da')->references('id')->on('users'); $table->unsignedBigInteger('mov_fk_tags'); diff --git a/public/js/app/movimenti.js b/public/js/app/movimenti.js index 6ee803a..628254d 100644 --- a/public/js/app/movimenti.js +++ b/public/js/app/movimenti.js @@ -91,6 +91,7 @@ $.getJSON("/admin/service/contolist", {}, function(contis) { }); }); +// Modifica movimento $(document).on('click', '.open_modal_modifica', function() { var url = "/admin/movimenti/modify"; var riga_id = $(this).val(); @@ -135,9 +136,9 @@ $(document).on('click', '.open_modal_modifica', function() { ); }); $('.modal-title').text('Modifica movimento'); - $('#data').val(data[0].mov_data); + $('#data').val(data[0].mov_data.substring(0,10)); $('#descrizione').val(data[0].mov_descrizione); - $('#importo').val(data[0].mov_importo); + $('#importo').val(data[0].mov_importo_dare); $('#myModal').modal('show'); // $('.panel-heading').text('Modifica movimento'); diff --git a/resources/views/conti/movimenti/list.blade.php b/resources/views/conti/movimenti/list.blade.php index 59380b1..caf7904 100644 --- a/resources/views/conti/movimenti/list.blade.php +++ b/resources/views/conti/movimenti/list.blade.php @@ -32,7 +32,8 @@ Data Categoria - Conto + Conto Dare + Conto Avere Descrizione Importo Dare Importo Avere @@ -42,13 +43,13 @@ @foreach( $movimenti as $movimento ) - {{ $movimento->mov_data}} {{ $movimento->cat_name }} - {{ $movimento->nomeConto }} + {{ $movimento->nomeContoDare ?? '' }} + {{ $movimento->nomeContoAvere ?? '' }} {{ $movimento->mov_descrizione }} - € {{ $movimento->mov_importo_dare }} - € {{ $movimento->mov_importo_avere }} + {{ $movimento->mov_importo_dare ." €"}} + {{ $movimento->mov_importo_avere." €" }}     @@ -71,6 +72,8 @@
+ +