Browse Source

Fix ingressi/uscite

Luca Parisio 1 năm trước cách đây
mục cha
commit
d1e829c308

+ 1 - 0
app/Http/Livewire/Categories.php

@@ -13,6 +13,7 @@ class Categories extends Component
 
     public function render()
     {
+        $this->emit('hideMsg');
         $reset = false;
         if ($this->level_1_id > 0)
         {

+ 88 - 0
app/Http/Livewire/Courses.php

@@ -0,0 +1,88 @@
+<?php
+namespace App\Http\Livewire;
+use Livewire\Component;
+class Courses extends Component
+{
+    public $level_1 = [];
+    public $level_2 = [];
+    public $level_3 = [];
+
+    public $level_1_id = 0;
+    public $level_2_id = 0;
+    public $level_3_id = 0;
+
+    public $course_id = null;
+
+    public function mount($course_id)
+    {
+        $this->course_id = $course_id;
+        if ($this->course_id != null)
+        {
+            $c = \App\Models\Course::findOrFail($this->course_id);
+            $ids = array_reverse($c->recursiveParent($c->parent_id, [$c->id]));
+            foreach($ids as $ii => $i)
+            {
+                if ($ii == 0)
+                {
+                    $this->level_1_id = $i;
+                }
+                if ($ii == 1)
+                {
+                    $this->level_2_id = $i;
+                }
+                if ($ii == 2)
+                {
+                    $this->level_3_id = $i;
+                }
+            }
+
+        }
+    }
+
+    public function updatedLevel1Id() {
+        $this->emit('setCourse', null);
+        $this->level_2_id = 0;
+        $this->level_2 = [];
+        $this->level_3_id = 0;
+        $this->level_3 = [];
+    }
+    public function updatedLevel2Id() {
+        $this->emit('setCourse', null);
+        $this->level_3_id = 0;
+        $this->level_3 = [];
+    }
+    public function updatedLevel3Id() {
+        $this->emit('setCourse', null);
+    }
+
+    public function render()
+    {
+        $reset = false;
+        if ($this->level_1_id > 0)
+        {
+            $this->level_2 = \App\Models\Course::where('parent_id', $this->level_1_id)->orderBy('name')->get();
+            if (sizeof($this->level_2) == 0)
+            {
+                $this->emit('setCourse', $this->level_1_id);
+                $reset = true;
+            }
+        }
+        if ($this->level_2_id > 0)
+        {
+            $this->level_3 = \App\Models\Course::where('parent_id', $this->level_2_id)->orderBy('name')->get();
+            if (sizeof($this->level_3) == 0)
+            {
+                $this->emit('setCourse', $this->level_2_id);
+                $reset = true;
+            }
+        }
+        if ($this->level_3_id > 0)
+        {
+            $this->emit('setCourse', $this->level_3_id);
+            $reset = true;
+        }
+        $this->level_1 = \App\Models\Course::where('parent_id', null)->orderBy('name')->get();
+
+        return view('livewire.courses');
+    }
+}

+ 133 - 34
app/Http/Livewire/Member.php

@@ -5,20 +5,24 @@ namespace App\Http\Livewire;
 use Livewire\Component;
 use Livewire\Attributes\Url;
 use Livewire\WithFileUploads;
+use Livewire\WithPagination;
 
 use DateTime;
 
 class Member extends Component
 {
 
-    protected $listeners = ['storeCategoryWithID' => 'storeCategoryWithID'];
+    use WithPagination;
+    protected $paginationTheme = 'bootstrap';
 
+    protected $listeners = ['storeCategoryWithID' => 'storeCategoryWithID',  'setCourse' => 'setCourse', 'hideMsg' => 'hideMsg'];
 
     use WithFileUploads;
 
-    public $sortField ='date';
-    public $sortAsc = true;
+    public $sortField ='id';
+    public $sortAsc = false;
 
+    public $groupMsg = '';
 
     public function sortBy($field)
     {
@@ -90,6 +94,13 @@ class Member extends Component
     // Certificates data
     public $member_certificates = array(), $certificate_type, $certificate_filename_old, $certificate_filename, $certificate_expire_date, $certificate_status, $addCertificate, $updateCertificate, $certificateDataId;
 
+    public $filterCard = [];
+    public $filterCategory = [];
+    public $filterCertNormal = 0;
+    public $filterCertAgonistic = 0;
+    public $filterCertScaduto = 0;
+    public $filterCertInScadenza = 0;
+
     protected $rules = [
         'first_name' => 'required',
         'last_name' => 'required',
@@ -184,6 +195,11 @@ class Member extends Component
 
     public $documents = [];
 
+    public function removeDocument($idx)
+    {
+        unset($this->document_files[$idx]);
+    }
+
     public function updatedDocuments()
     {
         foreach ($this->documents as $document)
@@ -331,29 +347,87 @@ class Member extends Component
 
     public function advancedSearch()
     {
-        $this->avanced = true;
+        $this->advanced = true;
+    }
 
+    public function advancedSearchCancel()
+    {
+        $this->filterCard = [];
+        $this->filterCategory = [];
+        $this->filterCertNormal = 0;
+        $this->filterCertAgonistic = 0;
+        $this->filterCertScaduto = 0;
+        $this->filterCertInScadenza = 0;
+        $this->advanced = false;
     }
 
     public function render()
     {
 
-
-
+        $datas = [];
         if (!$this->advanced)
         {
             if ($this->search != '')
-                $this->records = \App\Models\Member::where('first_name', 'LIKE', '%' . $this->search . '%')->orWhere('last_name', 'LIKE', '%' . $this->search . '%')->orWhere('email', 'LIKE', '%' . $this->search . '%')->get();
+                $datas = \App\Models\Member::select('members.*') // , \DB::raw('SUM(records.id) As total'))
+                    ->where('first_name', 'LIKE', '%' . $this->search . '%')
+                    ->orWhere('last_name', 'LIKE', '%' . $this->search . '%')
+                    ->orWhere('email', 'LIKE', '%' . $this->search . '%');
+                //$this->records = \App\Models\Member::where('first_name', 'LIKE', '%' . $this->search . '%')->orWhere('last_name', 'LIKE', '%' . $this->search . '%')->orWhere('email', 'LIKE', '%' . $this->search . '%')->get();
             else
-                $this->records = \App\Models\Member::get();
+                //$this->records = \App\Models\Member::get();
+                $datas = \App\Models\Member::select('members.*');
         }
         else
         {
-            $this->records = \App\Models\Member::where('id', '>', 0);
+            //$this->records = \App\Models\Member::where('id', '>', 0);
+            $datas = \App\Models\Member::select('members.*')->where('id', '>', 0);
+            if (sizeof($this->filterCard) > 0)
+            {
+                $card_ids = \App\Models\MemberCard::whereIn('card_id', $this->filterCard)->pluck('member_id');
+                //$this->records->whereIn('id', $card_ids);
+                $datas = $datas->whereIn('id', $card_ids);
+            }
+            if (sizeof($this->filterCategory) > 0)
+            {
+                $cats_ids = \App\Models\MemberCategory::whereIn('category_id', $this->filterCategory)->pluck('member_id');
+                //$this->records->whereIn('id', $cats_ids);
+                $datas = $datas->whereIn('id', $cats_ids);
+            }
+            $certs = [];
+
+            if ($this->filterCertNormal > 0)
+            {
+                $normal = \App\Models\MemberCertificate::where('type', 'N')->pluck('member_id');
+                //$this->records->whereIn('id', $normal);
+                $datas = $datas->whereIn('id', $normal);;
+            }
+            if ($this->filterCertAgonistic > 0)
+            {
+                $agonistic = \App\Models\MemberCertificate::where('type', 'A')->pluck('member_id');
+                //$this->records->whereIn('id', $agonistic);
+                $datas = $datas->whereIn('id', $agonistic);
+            }
+            if ($this->filterCertScaduto > 0)
+            {
+                $scaduto = \App\Models\MemberCertificate::where('expire_date', '<', date("Y-m-d"))->pluck('member_id');
+                //$this->records->whereIn('id', $scaduto);
+                $datas = $datas->whereIn('id', $scaduto);
+            }
+            if ($this->filterCertInScadenza > 0)
+            {
+                $scaduto = \App\Models\MemberCertificate::whereBetween('expire_date', [date("Y-m-d"), date("Y-m-d", strtotime("+1 month"))])->pluck('member_id');
+                //$this->records->whereIn('id', $scaduto);
+                $datas = $datas->whereIn('id', $scaduto);
+            }
+            if (sizeof($certs) > 0)
+            {
+                //$this->records->whereIn('id', $certs);
+            }
+            //$this->records = $this->records->get();
 
-            $this->records = $this->records->get();
         }
 
+        /*
         foreach($this->records as $r)
         {
             $r->age = $r->getAge();
@@ -366,13 +440,16 @@ class Member extends Component
             $this->records = $this->records->sortBy($this->sortField);
         else
             $this->records = $this->records->sortByDesc($this->sortField);
+        */
+
+        $datas = $datas->orderBy($this->sortField, $this->sortAsc ? 'ASC' : 'DESC')->paginate(10);
 
         //$this->records = $this->records->get();
         $this->loadMemberCards();
         $this->loadMemberCourses();
         $this->loadMemberCategories();
         $this->loadMemberCertificates();
-        return view('livewire.member');
+        return view('livewire.member', ['datas' => $datas]);
     }
 
     public function loadMemberCards()
@@ -409,7 +486,7 @@ class Member extends Component
     public function add()
     {
         $this->emit('load-select');
-
+        $this->emit('hide-search');
         $this->showDetail = false;
         $this->resetFields();
         $this->add = true;
@@ -436,9 +513,9 @@ class Member extends Component
                 'first_name' => strtoupper($this->first_name),
                 'last_name' => strtoupper($this->last_name),
                 'status' => $this->status,
-                'birth_city_id' => $this->birth_city_id,
-                'birth_province_id' => $this->birth_province_id,
-                'birth_nation_id' => $this->birth_nation_id,
+                'birth_city_id' => $this->birth_city_id > 0 ? $this->birth_city_id : null,
+                'birth_province_id' => $this->birth_province_id > 0 ? $this->birth_province_id : null,
+                'birth_nation_id' => $this->birth_nation_id > 0 ? $this->birth_nation_id : null,
                 'birth_date' => $this->birth_date,
                 'birth_place' => $this->birth_place,
                 'father_name' => $this->father_name,
@@ -458,9 +535,9 @@ class Member extends Component
                 'fiscal_code' => $this->fiscal_code,
                 'address' => $this->address,
                 'zip_code' => $this->zip_code,
-                'nation_id' => $this->nation_id,
-                'province_id' => $this->province_id,
-                'city_id' => $this->city_id,
+                'nation_id' => $this->nation_id > 0 ? $this->nation_id : null,
+                'province_id' => $this->province_id > 0 ? $this->province_id : null,
+                'city_id' => $this->city_id > 0 ? $this->city_id : null,
                 'phone' => $this->phone,
                 'phone2' => $this->phone2,
                 'phone3' => $this->phone3,
@@ -492,7 +569,7 @@ class Member extends Component
 
     public function edit($id){
         $this->showDetail = false;
-
+        $this->emit('hide-search');
         try {
             $member = \App\Models\Member::findOrFail($id);
             if( !$member) {
@@ -581,9 +658,9 @@ class Member extends Component
                 'first_name' => strtoupper($this->first_name),
                 'last_name' => strtoupper($this->last_name),
                 'status' => $this->status,
-                'birth_city_id' => $this->birth_city_id,
-                'birth_province_id' => $this->birth_province_id,
-                'birth_nation_id' => $this->birth_nation_id,
+                'birth_city_id' => $this->birth_city_id > 0 ? $this->birth_city_id : null,
+                'birth_province_id' => $this->birth_province_id > 0 ? $this->birth_province_id : null,
+                'birth_nation_id' => $this->birth_nation_id > 0 ? $this->birth_nation_id : null,
                 'birth_date' => $this->birth_date,
                 'birth_place' => $this->birth_place,
                 'father_name' => $this->father_name,
@@ -603,9 +680,9 @@ class Member extends Component
                 'fiscal_code' => $this->fiscal_code,
                 'address' => $this->address,
                 'zip_code' => $this->zip_code,
-                'nation_id' => $this->nation_id,
-                'province_id' => $this->province_id,
-                'city_id' => $this->city_id,
+                'nation_id' => $this->nation_id > 0 ? $this->nation_id : null,
+                'province_id' => $this->province_id > 0 ? $this->province_id : null,
+                'city_id' => $this->city_id > 0 ? $this->city_id : null,
                 'image' => $name != '' ? $name : $this->image_old,
                 'phone' => $this->phone,
                 'phone2' => $this->phone2,
@@ -693,7 +770,12 @@ class Member extends Component
                 $card = \App\Models\Card::findOrFail($this->card_card_id);
                 if ($card->next_day_expire > 0 && $card->next_month_expire > 0)
                 {
+
                     $m = strlen($card->next_month_expire) == 1 ? ('0' . $card->next_month_expire) : $card->next_month_expire;
+
+                    if (date("md", strtotime($this->card_date)) > ($m . $card->next_day_expire))
+                        $y += 1;
+
                     $next_exp = date($y . "-" . $m . "-" . $card->next_day_expire);
 
                     if ($next_exp > $this->card_date)
@@ -1058,18 +1140,30 @@ class Member extends Component
         }
     }
 
-    public function storeCategoryWithID($id)
+    public function hideMsg()
     {
+        $this->groupMsg = '';
+    }
 
+    public function storeCategoryWithID($id)
+    {
+        $this->groupMsg = '';
         try {
-            \App\Models\MemberCategory::create([
-                'member_id' => $this->dataId,
-                'category_id' => $id,
-                'date' => \Carbon\Carbon::now()
-            ]);
-            session()->flash('success, Associazione creato');
-            $this->resetCategoryFields();
-            $this->addCard = false;
+            if (\App\Models\MemberCategory::where('member_id', $this->dataId)->where('category_id', $id)->first())
+            {
+                $this->groupMsg = '<br>Attenzione, questo corso è stato già inserito';
+            }
+            else
+            {
+                \App\Models\MemberCategory::create([
+                    'member_id' => $this->dataId,
+                    'category_id' => $id,
+                    'date' => \Carbon\Carbon::now()
+                ]);
+                session()->flash('success, Associazione creato');
+                $this->resetCategoryFields();
+                $this->addCard = false;
+            }
         } catch (\Exception $ex) {
             session()->flash('error','Errore (' . $ex->getMessage() . ')');
         }
@@ -1085,6 +1179,11 @@ class Member extends Component
         }
     }
 
+    public function setCourse($id)
+    {
+        $this->course_course_id = $id;
+    }
+
     public function getNation($nation)
     {
         if ($nation > 0)

+ 3 - 1
app/Http/Livewire/Record.php

@@ -223,7 +223,9 @@ class Record extends Component
 
             $causalCheck = \App\Models\Causal::findOrFail($data->causal_id);
 
-            if ($causalCheck->no_first == null || !$causalCheck->no_first)
+            $paymentCheck = $data->payment_method->money;
+
+            if (!$paymentCheck && ($causalCheck->no_first == null || !$causalCheck->no_first))
             {
 
                 $amount = $data->amount;

+ 94 - 43
app/Http/Livewire/RecordIN.php

@@ -2,15 +2,21 @@
 
 namespace App\Http\Livewire;
 use Livewire\Component;
+use Livewire\WithPagination;
+use Barryvdh\DomPDF\Facade\Pdf;
 
 class RecordIN extends Component
 {
+    use WithPagination;
+    protected $paginationTheme = 'bootstrap';
 
     protected $listeners = ['setCausal' => 'setCausal'];
 
     public $sortField ='date';
     public $sortAsc = false;
 
+    public $typeIN = "IN";
+
     public $isDuplicate = false;
 
     public function sortBy($field)
@@ -267,11 +273,16 @@ class RecordIN extends Component
 
     public function render()
     {
-
+        $datas = [];
         if ($this->hasFilter)
         {
 
-            $datas = \App\Models\Record::where('type', 'IN')->with('member', 'payment_method');
+            $datas = \App\Models\Record::select('records.*', \DB::raw('members.first_name as first_name'), \DB::raw('members.last_name as last_name'), \DB::raw('payment_methods.name as payment')) // , \DB::raw('SUM(records.id) As total'))
+                    ->leftJoin('members', 'records.member_id', '=', 'members.id')
+                    ->leftJoin('payment_methods', 'records.payment_method_id', '=', 'payment_methods.id')
+                    ->where('records.type', 'IN');
+
+            // $datas = \App\Models\Record::where('type', 'IN')->with('member', 'payment_method');
             /*if ($this->filterCommercial > 0)
             {
                 $datas = $datas->where('commercial', $this->filterCommercial == 1 ? true : false);
@@ -298,10 +309,10 @@ class RecordIN extends Component
             }
             // $this->records = $datas->orderBy('date', 'DESC')->get();
 
-            $this->records = $datas->get();
+            //$this->records = $datas->get();
 
             $this->total = 0;
-            foreach($this->records as $r)
+            foreach($datas->get() as $r)
             {
                 foreach($r->rows as $rr)
                 {
@@ -309,6 +320,8 @@ class RecordIN extends Component
                 }
             }
 
+            $datas = $datas->orderBy($this->sortField, $this->sortAsc ? 'ASC' : 'DESC')->paginate(20);
+
             //$this->total = $this->records->sum('amount');
 
         }
@@ -316,7 +329,15 @@ class RecordIN extends Component
         {
             if ($this->selectedFilter == '')
             {
-                $this->records = \App\Models\Record::where('type', 'IN')->with('member', 'payment_method')->limit(20)->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get();
+                // $this->records = \App\Models\Record::where('type', 'IN')->with('member', 'payment_method')->limit(20)->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get();
+
+                $datas = \App\Models\Record::select('records.*', \DB::raw('members.first_name as first_name'), \DB::raw('members.last_name as last_name'), \DB::raw('payment_methods.name as payment')) // , \DB::raw('SUM(records.id) As total'))
+                    ->leftJoin('members', 'records.member_id', '=', 'members.id')
+                    ->leftJoin('payment_methods', 'records.payment_method_id', '=', 'payment_methods.id')
+                    ->where('records.type', 'IN')
+                    ->orderBy($this->sortField, $this->sortAsc ? 'ASC' : 'DESC')
+                    ->paginate(20);
+
             }
             else
             {
@@ -340,10 +361,24 @@ class RecordIN extends Component
                     $fromDate = date("2000-01-01");
                     $toDate = date("Y-12-31");
                 }
+                /*
                 $this->records = \App\Models\Record::where('type', 'IN')->whereBetween('date', [$fromDate, $toDate])->with('member', 'payment_method')->get();
+                $datas = \App\Models\Record::select('records.*', \DB::raw('members.first_name as first_name'), \DB::raw('members.last_name as last_name'), \DB::raw('payment_methods.name as payment'), \DB::raw('SUM(records.id) As total'))
+                    ->leftJoin('members', 'records.member_id', '=', 'members.id')
+                    ->leftJoin('payment_methods', 'records.payment_method_id', '=', 'payment_methods.id')
+                    //->where('analytics.date', Carbon::today()->toDateString())
+                    ->paginate(1);*/
+                $datas = \App\Models\Record::select('records.*', \DB::raw('members.first_name as first_name'), \DB::raw('members.last_name as last_name'), \DB::raw('payment_methods.name as payment')) // , \DB::raw('SUM(records.id) As total'))
+                    ->leftJoin('members', 'records.member_id', '=', 'members.id')
+                    ->leftJoin('payment_methods', 'records.payment_method_id', '=', 'payment_methods.id')
+                    ->where('records.type', 'IN')
+                    ->whereBetween('date', [$fromDate, $toDate])
+                    ->orderBy($this->sortField, $this->sortAsc ? 'ASC' : 'DESC')
+                    ->paginate(20);
             }
         }
 
+        /*
         foreach($this->records as $r)
         {
             $r->total = $r->getTotal();
@@ -360,8 +395,9 @@ class RecordIN extends Component
         }
         else
             $this->records = $this->records->sortByDesc('id');
+        */
 
-        return view('livewire.records_in');
+        return view('livewire.records_in', ['datas' => $datas]);
     }
 
     public function executeMultipleAction(){
@@ -489,8 +525,6 @@ class RecordIN extends Component
                 $this->update = true;
                 $this->add = false;
 
-
-
                 $this->rows = \App\Models\RecordRow::where('record_id', $this->dataId)->select('causal_id', 'note', 'commercial', 'when', 'amount')->get()->toArray();
                 foreach($this->rows as $i => $r)
                 {
@@ -498,7 +532,7 @@ class RecordIN extends Component
                     $this->rows[$i]['when'] = json_decode($this->rows[$i]['when']);
                 }
 
-                $exist = \App\Models\Receipt::where('record_id', $id)->first();
+                $exist = \App\Models\Receipt::where('record_id', $id)->orderBy('id', 'DESC')->first();
                 if ($exist != null)
                     $this->currentReceip = $exist;
             }
@@ -665,38 +699,24 @@ class RecordIN extends Component
     public function createReceipt()
     {
 
-        $receipt = \App\Models\Receipt::where('record_id', $this->dataId)->first();
+        $create = false;
+        $receipt = \App\Models\Receipt::where('record_id', $this->dataId)->orderBy('id', 'DESC')->first();
         if ($receipt != null)
         {
-            $receipt->update([
-                'member_id' => $this->member_id,
-                'supplier_id' => $this->supplier_id,
-                // 'causal_id' => $this->causal_id,
-                'payment_method_id' => $this->payment_method_id,
-                'date' => date("Y-m-d", strtotime($this->date)),
-                //'month' => $this->month,
-                //'year' => $this->year,
-                'type' => $this->type,
-                //'amount' => $this->currencyToDouble($this->amount),
-                //'commercial' => $this->commercial,
-                'status' => 1,
-            ]);
 
-            \App\Models\ReceiptRow::where('receip_id', $receipt->id)->delete();
-            foreach($this->rows as $row)
+            // Controllo lo stato, se 99 ne genero una nuova
+            if ($receipt->status == 99)
             {
-                \App\Models\ReceiptRow::create([
-                    'receip_id' => $receipt->id,
-                    'causal_id' => $row["causal_id"],
-                    'note' => $row["note"],
-                    'amount' => $this->currencyToDouble($row["amount"]),
-                    'commercial' => $row["commercial"],
-                    'when' => json_encode($row["when"])
-                ]);
+                $create = true;
             }
 
         }
         else
+        {
+            $create = true;
+        }
+
+        if ($create)
         {
             $number = 1;
             $exist = \App\Models\Receipt::where('year', date("Y"))->orderBy('number', 'DESC')->first();
@@ -735,16 +755,6 @@ class RecordIN extends Component
 
         }
 
-        /*
-        $data = [
-            'member' => $receipt->id
-            ];
-
-        $pdf = \PDF::loadView('partials.pdf_generate_connections', $data)->setPaper('a4', 'landscape')->output(); //
-        return response()->streamDownload(
-            fn() => print($pdf), 'export_protocol.pdf'
-        );
-        */
 
     }
 
@@ -805,4 +815,45 @@ class RecordIN extends Component
         $this->rows[$idx]["causal_id"] = $id;
     }
 
+    public function printReceipt()
+    {
+        //$pdf = PDF::loadView('pdf/receipt', array('datas' => $datas, 'from' => $x, 'to' => $y, 'who' => '', 'matricola' => $matricola));
+        $pdf = PDF::loadView('receipt', array('receipt' => $this->currentReceip))->output();
+        return response()->streamDownload(
+            fn () => print($pdf),
+            "ricevuta_" . $this->currentReceip->number . "_" . $this->currentReceip->year . ".pdf"
+        );
+        /*return response()->streamDownload(function () {
+            echo $pdf->stream();
+        }, 'test.pdf');*/
+    }
+
 }
+
+/*
+<!--<table width="100%" cellpadding="7">
+      <tr>
+        <td><b>Cliente</b></td>
+        <td><b>Data/ora ingresso</b></td>
+        <td><b>Data/ora uscita</b></td>
+      </tr>
+      @foreach ($datas as $data)
+      <tr>
+        <td>{{ $data["cliente"] }}</td>
+        <td>
+            @if($data["ingresso"] != '')
+                <span style="color:green">{{ date("d/m/Y H:i:s", strtotime($data["ingresso"])) }}</span>
+            @endif
+        </td>
+        <td>
+            @if($data["uscita"] != '')
+                <span style="color:red">{{ date("d/m/Y H:i:s", strtotime($data["uscita"])) }}</span>
+            @endif
+        </td>
+      </tr>
+      @endforeach
+    </table>-->
+    <footer>
+        <small>{{date("d/m/Y H:i:s")}}</small>
+    </footer>
+    */

+ 432 - 56
app/Http/Livewire/RecordINOUT.php

@@ -3,15 +3,36 @@
 namespace App\Http\Livewire;
 use Livewire\Component;
 
+use PhpOffice\PhpSpreadsheet\Spreadsheet;
+use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
+
 class RecordINOUT extends Component
 {
-    public $records_in, $records_out;
+    //public $records_in, $records_out;
     public $total_in = 0;
     public $total_out = 0;
 
+    public $datas = [];
     public $month;
     public $year;
 
+    public $months_1 = [];
+    public $year_1;
+
+    public $months_2 = [];
+    public $year_2;
+    public $show_block_2;
+
+    public $borsellino_id = 0;
+
+    public $columns = array();
+    public $rows_in = array();
+    public $rows_out = array();
+    public $records_in = array();
+    public $records_out = array();
+
+    public $showData = true;
+
     public $hasFilter = false;
 
     public $total = 0;
@@ -25,90 +46,185 @@ class RecordINOUT extends Component
     public function mount()
     {
 
-        $this->month = date("n");
+        $borsellino = \App\Models\Causal::where('money', true)->first();
+        if ($borsellino)
+            $this->borsellino_id = $borsellino->id;
+
+        //$this->month = 1;
         $this->year = date("Y");
-        /*$this->causals = array();
+        $this->year_1 = date("Y");
+        $this->year_2 = date("Y");
+        $this->show_block_2 = false;
 
-        $this->getCausale(\App\Models\Causal::select('id', 'name')->where('parent_id', null)->where('type', 'IN')->get(), 0);
+        $this->getCausale(\App\Models\Causal::select('id', 'name')->where('parent_id', null)->where('type', 'IN')->get(), 'IN', 0);
+        $this->getCausale(\App\Models\Causal::select('id', 'name')->where('parent_id', null)->where('type', 'OUT')->get(), 'OUT', 0);
 
-        $this->members = \App\Models\Member::select(['id', 'first_name', 'last_name', 'fiscal_code'])->orderBy('last_name')->orderBy('first_name')->get();
-        $this->payments = \App\Models\PaymentMethod::select('id', 'name')->orderBy('name')->get();
+    }
 
-        if ($this->first)
+    public function getCausale($records, $type, $indentation)
+    {
+        foreach($records as $record)
         {
-            if (isset($_GET["new"]))
-            {
-                $this->refreshAfter = 1;
-                $this->add();
-            }
-            if (isset($_GET["memberId"]))
-                $this->member_id = $_GET["memberId"];
-            if (isset($_GET["causalId"]))
-                $this->causal_id = $_GET["causalId"];
+            if ($type == 'IN')
+                $this->rows_in[] = array('id' => $record->id, 'name' => $record->name, 'level' => $indentation, 'parent_id' => $record->parent_id);
+            if ($type == 'OUT')
+                $this->rows_out[] = array('id' => $record->id, 'name' => $record->name, 'level' => $indentation, 'parent_id' => $record->parent_id);
+            if(count($record->childs))
+                $this->getCausale($record->childs, $type, $indentation + 1);
         }
-        $this->first = false;*/
-
     }
 
     public function render()
     {
+        return view('livewire.records_in_out');
+    }
 
-        $my = $this->month . "-" . $this->year;
+    public function hydrate()
+    {
+        //$this->emit('load-select');
+    }
 
-        // $datas_in = \App\Models\Record::where('type', 'IN')->with('member', 'payment_method');
-        $datas_in = \App\Models\Record::where('type', 'IN')->with('member', 'payment_method')
-                    ->join('records_rows', 'records.id', '=', 'records_rows.record_id')
-                    ->where('records_rows.when', 'like', '%' . $my . '%');
+    public function show($m, $y)
+    //public function show($dt)
+    {
+        //list($m, $y) = explode("_", $dt);
+
+        if ($m != "" && $y != "")
+            $this->datas[] = $m . "-" . $y;
 
-        $this->records_in = $datas_in->orderBy('date', 'DESC')->get();
+        $this->columns = array();
+        $this->records_in = [];
+        $this->records_out = [];
 
-        $this->total_in = 0;
-        foreach($this->records_in as $in)
+        if (sizeof($this->datas) > 0)
         {
-            $amount = $in->amount;
-            $when = sizeof(json_decode($in->when));
-            if ($when > 1)
+            foreach($this->datas as $filter)
             {
-                $amount = $amount / $when;
-                $in->amount = $amount;
+                // $filter = $m . "-" . $this->year;
+
+                $this->columns[] = $filter;
+
+                $records = \App\Models\Record::where('type', 'IN')
+                    ->join('records_rows', 'records.id', '=', 'records_rows.record_id')
+                    ->where('records_rows.causal_id', '<>', $this->borsellino_id)
+                    ->where('records_rows.when', 'like', '%' . $filter . '%')->get();
+                //$records = $records->orderBy('date', 'DESC')->get();
+
+                foreach($records as $record)
+                {
+                    $amount = $record->amount;
+                    $when = sizeof(json_decode($record->when));
+                    if ($when > 1)
+                    {
+                        $amount = $amount / $when;
+                        $record->amount = $amount;
+                    }
+                    // Aggiungo/aggiorno i dati
+                    if (isset($this->records_in[$filter][$record->causal_id]))
+                        $this->records_in[$filter][$record->causal_id] += $amount;
+                    else
+                        $this->records_in[$filter][$record->causal_id] = $amount;
+                    // Aggiorno i dati del padre
+                    $this->updateParent("IN", $record->causal_id, $amount, $filter);
+                }
+
+                $records = \App\Models\Record::where('type', 'OUT')
+                    ->join('records_rows', 'records.id', '=', 'records_rows.record_id')
+                    ->where('records_rows.causal_id', '<>', $this->borsellino_id)
+                    ->where('records_rows.when', 'like', '%' . $filter . '%')->get();
+                //$records = $records->orderBy('date', 'DESC')->get();
+
+                foreach($records as $record)
+                {
+                    $amount = $record->amount;
+                    $when = sizeof(json_decode($record->when));
+                    if ($when > 1)
+                    {
+                        $amount = $amount / $when;
+                        $record->amount = $amount;
+                    }
+                    // Aggiungo/aggiorno i dati
+                    if (isset($this->records_out[$filter][$record->causal_id]))
+                        $this->records_out[$filter][$record->causal_id] += $amount;
+                    else
+                        $this->records_out[$filter][$record->causal_id] = $amount;
+                    $this->updateParent("OUT", $record->causal_id, $amount, $filter);
+                }
+
             }
-            $this->total_in += $amount;
         }
 
-        // $this->total_in = $this->records_in->sum('amount');
+        //$this->showData = true;
+        $this->emit('load-table');
 
-        $datas_out = \App\Models\Record::where('type', 'OUT')->with('member', 'payment_method')
-                    ->join('records_rows', 'records.id', '=', 'records_rows.record_id')
-                    ->where('records_rows.when', 'like', '%' . $my . '%');
-                    /*
-        $datas_out = \App\Models\Record::where('type', 'OUT')->with('supplier', 'causal', 'payment_method');
-        if ($this->month > 0)
+    }
+
+    public function updateParent($type, $causal_id, $amount, $filter)
+    {
+        if ($type == "IN")
         {
-            $datas_out = $datas_out->where('month', $this->month);
+            foreach($this->rows_in as $r)
+            {
+                if ($r["id"] == $causal_id)
+                {
+                    if (isset($this->records_in[$filter][$r["parent_id"]]))
+                        $this->records_in[$filter][$r["parent_id"]] += $amount;
+                    else
+                        $this->records_in[$filter][$r["parent_id"]] = $amount;
+                    if ($r["parent_id"] > 0)
+                        $this->updateParent("IN", $r["parent_id"], $amount, $filter);
+                }
+            }
         }
-        if ($this->year > 0)
+        if ($type == "OUT")
         {
-            $datas_out = $datas_out->where('year', $this->year);
+            foreach($this->rows_out as $r)
+            {
+                if ($r["id"] == $causal_id)
+                {
+                    if (isset($this->records_out[$filter][$r["parent_id"]]))
+                        $this->records_out[$filter][$r["parent_id"]] += $amount;
+                    else
+                        $this->records_out[$filter][$r["parent_id"]] = $amount;
+                    if ($r["parent_id"] > 0)
+                        $this->updateParent("OUT", $r["parent_id"], $amount, $filter);
+                }
+            }
         }
-        */
-        $this->records_out = $datas_out->orderBy('date', 'DESC')->get();
-
-        // $this->total_out = $this->records_out->sum('amount');
+    }
 
-        $this->total_out = 0;
-        foreach($this->records_out as $out)
+    public function updateParentYear($type, $causal_id, $amount, $filter, &$records_in, &$records_out)
+    {
+        if ($type == "IN")
         {
-            $amount = $out->amount;
-            $when = sizeof(json_decode($out->when));
-            if ($when > 1)
+            foreach($this->rows_in as $r)
             {
-                $amount = $amount / $when;
-                $out->amount = $amount;
+                if ($r["id"] == $causal_id)
+                {
+                    if (isset($records_in[$filter][$r["parent_id"]]))
+                        $records_in[$filter][$r["parent_id"]] += $amount;
+                    else
+                        $records_in[$filter][$r["parent_id"]] = $amount;
+                    if ($r["parent_id"] > 0)
+                        $this->updateParentYear("IN", $r["parent_id"], $amount, $filter, $records_in, $records_out);
+                }
+            }
+        }
+        if ($type == "OUT")
+        {
+            foreach($this->rows_out as $r)
+            {
+                if ($r["id"] == $causal_id)
+                {
+                    if (isset($records_out[$filter][$r["parent_id"]]))
+                        $records_out[$filter][$r["parent_id"]] += $amount;
+                    else
+                        $records_out[$filter][$r["parent_id"]] = $amount;
+                    if ($r["parent_id"] > 0)
+                        $this->updateParentYear("OUT", $r["parent_id"], $amount, $filter, $records_in, $records_out);
+                }
             }
-            $this->total_out += $amount;
         }
-
-        return view('livewire.records_in_out');
     }
 
     public function getCausal($causal)
@@ -121,4 +237,264 @@ class RecordINOUT extends Component
         return $ret;
     }
 
+    public function getMonth($str)
+    {
+        $ret = '';
+        list($m, $y) = explode("-", $str);
+        switch ($m) {
+            case '01':
+                $ret = 'Gennaio ';
+                break;
+            case '02':
+                $ret = 'Febbraio ';
+                break;
+            case '03':
+                $ret = 'Marzo ';
+                break;
+            case '04':
+                $ret = 'Aprile ';
+                break;
+            case '05':
+                $ret = 'Maggio ';
+                break;
+            case '06':
+                $ret = 'Giugno ';
+                break;
+            case '07':
+                $ret = 'Luglio ';
+                break;
+            case '08':
+                $ret = 'Agosto ';
+                break;
+            case '09':
+                $ret = 'Settembre ';
+                break;
+            case '10':
+                $ret = 'Ottobre ';
+                break;
+            case '11':
+                $ret = 'Novembre ';
+                break;
+            case '12':
+                $ret = 'Dicembre ';
+                break;
+            default:
+                $ret = '';
+                break;
+        }
+        $ret .= $y;
+        return $ret;
+    }
+
+    public function clear()
+    {
+        $this->columns = [];
+        $this->datas = [];
+        $this->records_out = [];
+        $this->records_in = [];
+        $this->emit('load-select');
+        //$this->showData = false;
+    }
+
+    public function remove($idx)
+    {
+        unset($this->datas[$idx]);
+        $this->show('', '');
+    }
+
+    public function export()
+    {
+
+        $path = $this->generateExcel($this->columns, $this->rows_in, $this->records_in, $this->rows_out, $this->records_out);
+        return response()->download($path)->deleteFileAfterSend();
+
+    }
+
+    public function exportYear()
+    {
+        $records_in = [];
+        $records_out = [];
+        $datas = [];
+        for($m=1;$m<=12;$m++)
+        {
+            $datas[] = $m . "-" . $this->year;
+        }
+        foreach($datas as $filter)
+        {
+
+            $columns[] = $filter;
+
+            $records = \App\Models\Record::where('type', 'IN')
+                ->join('records_rows', 'records.id', '=', 'records_rows.record_id')
+                ->where('records_rows.causal_id', '<>', $this->borsellino_id)
+                ->where('records_rows.when', 'like', '%' . $filter . '%')->get();
+            //$records = $records->orderBy('date', 'DESC')->get();
+
+            foreach($records as $record)
+            {
+                $amount = $record->amount;
+                $when = sizeof(json_decode($record->when));
+                if ($when > 1)
+                {
+                    $amount = $amount / $when;
+                    $record->amount = $amount;
+                }
+                // Aggiungo/aggiorno i dati
+                if (isset($records_in[$filter][$record->causal_id]))
+                    $records_in[$filter][$record->causal_id] += $amount;
+                else
+                    $records_in[$filter][$record->causal_id] = $amount;
+                // Aggiorno i dati del padre
+                $this->updateParentYear("IN", $record->causal_id, $amount, $filter, $records_in, $records_out);
+            }
+
+            $records = \App\Models\Record::where('type', 'OUT')
+                ->join('records_rows', 'records.id', '=', 'records_rows.record_id')
+                ->where('records_rows.causal_id', '<>', $this->borsellino_id)
+                ->where('records_rows.when', 'like', '%' . $filter . '%')->get();
+            //$records = $records->orderBy('date', 'DESC')->get();
+
+            foreach($records as $record)
+            {
+                $amount = $record->amount;
+                $when = sizeof(json_decode($record->when));
+                if ($when > 1)
+                {
+                    $amount = $amount / $when;
+                    $record->amount = $amount;
+                }
+                // Aggiungo/aggiorno i dati
+                if (isset($records_out[$filter][$record->causal_id]))
+                    $records_out[$filter][$record->causal_id] += $amount;
+                else
+                    $records_out[$filter][$record->causal_id] = $amount;
+                $this->updateParentYear("OUT", $record->causal_id, $amount, $filter, $records_in, $records_out);
+            }
+
+        }
+
+        $path = $this->generateExcel($columns, $this->rows_in, $records_in, $this->rows_out, $records_out);
+        return response()->download($path)->deleteFileAfterSend();
+
+    }
+
+    public function generateExcel($columns, $rows_in, $records_in, $rows_out, $records_out)
+    {
+        $letters = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N');
+
+        $spreadsheet = new Spreadsheet();
+        $activeWorksheet = $spreadsheet->getActiveSheet();
+
+        $activeWorksheet->setCellValue('A1', 'Entrate');
+        foreach($columns as $idx => $column)
+        {
+            $activeWorksheet->setCellValue($letters[$idx + 1] . '1', $this->getMonth($column));
+        }
+
+        $activeWorksheet->getStyle('A1:N1')->getFont()->setBold(true);
+        $activeWorksheet->getStyle('A1:N1')->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('00ff00');
+
+        $count = 2;
+
+        $totals = [];
+
+        foreach($rows_in as $in)
+        {
+            $activeWorksheet->setCellValue('A' . $count, str_repeat("  ", $in["level"]) . $in["name"]);
+
+            foreach($columns as $idx => $column)
+            {
+                if(isset($records_in[$column][$in["id"]]))
+                {
+                    $activeWorksheet->setCellValue($letters[$idx + 1] . $count, formatPrice($records_in[$column][$in["id"]]));
+                    if ($in["level"] == 0)
+                    {
+                        if (isset($totals[$idx]))
+                            $totals[$idx] += $records_in[$column][$in["id"]];
+                        else
+                            $totals[$idx] = $records_in[$column][$in["id"]];
+                    }
+                }
+            }
+
+            if ($in["level"] == 0)
+            {
+                $activeWorksheet->getStyle('A' . $count . ':N' . $count)->getFont()->setBold(true);
+                $activeWorksheet->getStyle('A' . $count . ':N' . $count)->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('b1ed5c');
+            }
+
+            $count += 1;
+
+        }
+
+        $activeWorksheet->setCellValue('A' . $count, 'Totale');
+        foreach($totals as $idx => $total)
+        {
+            $activeWorksheet->setCellValue($letters[$idx + 1] . $count, formatPrice($total));
+            $activeWorksheet->getStyle('A' . $count . ':N' . $count)->getFont()->setBold(true);
+            $activeWorksheet->getStyle('A' . $count . ':N' . $count)->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('00ff00');
+        }
+
+
+        $count += 2;
+        $activeWorksheet->setCellValue('A' . $count, "Uscite");
+        foreach($columns as $idx => $column)
+        {
+            $activeWorksheet->setCellValue($letters[$idx + 1] . $count, $this->getMonth($column));
+        }
+
+        $activeWorksheet->getStyle('A' . $count . ':N' . $count)->getFont()->setBold(true);
+        $activeWorksheet->getStyle('A' . $count . ':N' . $count)->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('ff0000');
+
+        $count += 1;
+
+        $totals = [];
+
+        foreach($rows_out as $out)
+        {
+            $activeWorksheet->setCellValue('A' . $count, str_repeat("  ", $out["level"]) . $out["name"]);
+
+            foreach($columns as $idx => $column)
+            {
+                if(isset($records_out[$column][$out["id"]]))
+                {
+                    $activeWorksheet->setCellValue($letters[$idx + 1] . $count, formatPrice($records_out[$column][$out["id"]]));
+                    if ($out["level"] == 0)
+                    {
+                        if (isset($totals[$idx]))
+                            $totals[$idx] += $records_out[$column][$out["id"]];
+                        else
+                            $totals[$idx] = $records_out[$column][$out["id"]];
+                    }
+                }
+            }
+
+            if ($out["level"] == 0)
+            {
+                $activeWorksheet->getStyle('A' . $count . ':N' . $count)->getFont()->setBold(true);
+                $activeWorksheet->getStyle('A' . $count . ':N' . $count)->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('ed6d61');
+            }
+
+            $count += 1;
+
+        }
+
+        $activeWorksheet->setCellValue('A' . $count, 'Totale');
+        foreach($totals as $idx => $total)
+        {
+            $activeWorksheet->setCellValue($letters[$idx + 1] . $count, formatPrice($total));
+            $activeWorksheet->getStyle('A' . $count . ':N' . $count)->getFont()->setBold(true);
+            $activeWorksheet->getStyle('A' . $count . ':N' . $count)->getFill()->setFillType(\PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID)->getStartColor()->setARGB('ff0000');
+        }
+
+        foreach($letters as $l)
+            $activeWorksheet->getColumnDimension($l)->setWidth(20);
+
+        $writer = new Xlsx($spreadsheet);
+        $writer->save($path = storage_path('export.xlsx'));
+
+        return $path;
+
+    }
+
 }

+ 2 - 0
app/Http/Livewire/RecordOUT.php

@@ -11,6 +11,8 @@ class RecordOUT extends Component
     public $sortField ='date';
     public $sortAsc = false;
 
+    public $typeOUT = "OUT";
+
     public function sortBy($field)
     {
         if($this->sortField === $field)

+ 2 - 0
app/Models/Causal.php

@@ -57,6 +57,8 @@ class Causal extends Model
 
     public function recursiveParent($parent_id, $array)
     {
+        if ($parent_id == null)
+            return $array;
         $x = \App\Models\Causal::findOrFail($parent_id);
         $array[] = $x->id;
 

+ 17 - 0
app/Models/Course.php

@@ -55,4 +55,21 @@ class Course extends Model
         }
     }
 
+    public function recursiveParent($parent_id, $array)
+    {
+        if ($parent_id == null)
+            return $array;
+        $x = \App\Models\Course::findOrFail($parent_id);
+        $array[] = $x->id;
+
+        if ($x->parent_id != null)
+        {
+            return $this->recursiveParent($x->parent_id, $array);
+        }
+        else
+        {
+            return $array;
+        }
+    }
+
 }

+ 5 - 0
app/Models/Receipt.php

@@ -25,6 +25,11 @@ class Receipt extends Model
         'status'
     ];
 
+    public function rows()
+    {
+        return $this->hasMany(ReceiptRow::class, 'receip_id', 'id');
+    }
+
     public function record()
     {
         return $this->belongsTo(Record::class);

+ 1 - 1
app/helpers.php

@@ -12,5 +12,5 @@ function getCategories()
 
 function formatPrice($price)
 {
-    return "€ " . number_format($price, 2, ",", "");
+    return "€ " . number_format($price, 2, ",", ".");
 }

+ 3 - 1
composer.json

@@ -6,11 +6,13 @@
     "license": "MIT",
     "require": {
         "php": "^8.0.2",
+        "barryvdh/laravel-dompdf": "^2.1",
         "guzzlehttp/guzzle": "^7.2",
         "laravel/framework": "^9.19",
         "laravel/sanctum": "^3.0",
         "laravel/tinker": "^2.7",
-        "livewire/livewire": "^2.12"
+        "livewire/livewire": "^2.12",
+        "phpoffice/phpspreadsheet": "^2.0"
     },
     "require-dev": {
         "fakerphp/faker": "^1.9.1",

+ 929 - 9
composer.lock

@@ -4,8 +4,85 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "dd85ddbc1c708d755215db31483116a2",
+    "content-hash": "929f88783ff020750e47e3ae1b2963b4",
     "packages": [
+        {
+            "name": "barryvdh/laravel-dompdf",
+            "version": "v2.1.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/barryvdh/laravel-dompdf.git",
+                "reference": "cb37868365f9b937039d316727a1fced1e87b31c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/cb37868365f9b937039d316727a1fced1e87b31c",
+                "reference": "cb37868365f9b937039d316727a1fced1e87b31c",
+                "shasum": ""
+            },
+            "require": {
+                "dompdf/dompdf": "^2.0.3",
+                "illuminate/support": "^6|^7|^8|^9|^10|^11",
+                "php": "^7.2 || ^8.0"
+            },
+            "require-dev": {
+                "larastan/larastan": "^1.0|^2.7.0",
+                "orchestra/testbench": "^4|^5|^6|^7|^8|^9",
+                "phpro/grumphp": "^1 || ^2.5",
+                "squizlabs/php_codesniffer": "^3.5"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.0-dev"
+                },
+                "laravel": {
+                    "providers": [
+                        "Barryvdh\\DomPDF\\ServiceProvider"
+                    ],
+                    "aliases": {
+                        "Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf",
+                        "PDF": "Barryvdh\\DomPDF\\Facade\\Pdf"
+                    }
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Barryvdh\\DomPDF\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Barry vd. Heuvel",
+                    "email": "barryvdh@gmail.com"
+                }
+            ],
+            "description": "A DOMPDF Wrapper for Laravel",
+            "keywords": [
+                "dompdf",
+                "laravel",
+                "pdf"
+            ],
+            "support": {
+                "issues": "https://github.com/barryvdh/laravel-dompdf/issues",
+                "source": "https://github.com/barryvdh/laravel-dompdf/tree/v2.1.1"
+            },
+            "funding": [
+                {
+                    "url": "https://fruitcake.nl",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/barryvdh",
+                    "type": "github"
+                }
+            ],
+            "time": "2024-03-15T12:48:39+00:00"
+        },
         {
             "name": "brick/math",
             "version": "0.10.2",
@@ -349,6 +426,68 @@
             ],
             "time": "2022-12-14T08:49:07+00:00"
         },
+        {
+            "name": "dompdf/dompdf",
+            "version": "v2.0.4",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/dompdf/dompdf.git",
+                "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/dompdf/dompdf/zipball/093f2d9739cec57428e39ddadedfd4f3ae862c0f",
+                "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "ext-mbstring": "*",
+                "masterminds/html5": "^2.0",
+                "phenx/php-font-lib": ">=0.5.4 <1.0.0",
+                "phenx/php-svg-lib": ">=0.3.3 <1.0.0",
+                "php": "^7.1 || ^8.0"
+            },
+            "require-dev": {
+                "ext-json": "*",
+                "ext-zip": "*",
+                "mockery/mockery": "^1.3",
+                "phpunit/phpunit": "^7.5 || ^8 || ^9",
+                "squizlabs/php_codesniffer": "^3.5"
+            },
+            "suggest": {
+                "ext-gd": "Needed to process images",
+                "ext-gmagick": "Improves image processing performance",
+                "ext-imagick": "Improves image processing performance",
+                "ext-zlib": "Needed for pdf stream compression"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Dompdf\\": "src/"
+                },
+                "classmap": [
+                    "lib/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "LGPL-2.1"
+            ],
+            "authors": [
+                {
+                    "name": "The Dompdf Community",
+                    "homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md"
+                }
+            ],
+            "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
+            "homepage": "https://github.com/dompdf/dompdf",
+            "support": {
+                "issues": "https://github.com/dompdf/dompdf/issues",
+                "source": "https://github.com/dompdf/dompdf/tree/v2.0.4"
+            },
+            "time": "2023-12-12T20:19:39+00:00"
+        },
         {
             "name": "dragonmantank/cron-expression",
             "version": "v3.3.2",
@@ -1824,6 +1963,261 @@
             ],
             "time": "2023-03-03T20:12:38+00:00"
         },
+        {
+            "name": "maennchen/zipstream-php",
+            "version": "3.1.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/maennchen/ZipStream-PHP.git",
+                "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/b8174494eda667f7d13876b4a7bfef0f62a7c0d1",
+                "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1",
+                "shasum": ""
+            },
+            "require": {
+                "ext-mbstring": "*",
+                "ext-zlib": "*",
+                "php-64bit": "^8.1"
+            },
+            "require-dev": {
+                "ext-zip": "*",
+                "friendsofphp/php-cs-fixer": "^3.16",
+                "guzzlehttp/guzzle": "^7.5",
+                "mikey179/vfsstream": "^1.6",
+                "php-coveralls/php-coveralls": "^2.5",
+                "phpunit/phpunit": "^10.0",
+                "vimeo/psalm": "^5.0"
+            },
+            "suggest": {
+                "guzzlehttp/psr7": "^2.4",
+                "psr/http-message": "^2.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "ZipStream\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Paul Duncan",
+                    "email": "pabs@pablotron.org"
+                },
+                {
+                    "name": "Jonatan Männchen",
+                    "email": "jonatan@maennchen.ch"
+                },
+                {
+                    "name": "Jesse Donat",
+                    "email": "donatj@gmail.com"
+                },
+                {
+                    "name": "András Kolesár",
+                    "email": "kolesar@kolesar.hu"
+                }
+            ],
+            "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
+            "keywords": [
+                "stream",
+                "zip"
+            ],
+            "support": {
+                "issues": "https://github.com/maennchen/ZipStream-PHP/issues",
+                "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.0"
+            },
+            "funding": [
+                {
+                    "url": "https://github.com/maennchen",
+                    "type": "github"
+                },
+                {
+                    "url": "https://opencollective.com/zipstream",
+                    "type": "open_collective"
+                }
+            ],
+            "time": "2023-06-21T14:59:35+00:00"
+        },
+        {
+            "name": "markbaker/complex",
+            "version": "3.0.2",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/MarkBaker/PHPComplex.git",
+                "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
+                "reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.2 || ^8.0"
+            },
+            "require-dev": {
+                "dealerdirect/phpcodesniffer-composer-installer": "dev-master",
+                "phpcompatibility/php-compatibility": "^9.3",
+                "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
+                "squizlabs/php_codesniffer": "^3.7"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Complex\\": "classes/src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mark Baker",
+                    "email": "mark@lange.demon.co.uk"
+                }
+            ],
+            "description": "PHP Class for working with complex numbers",
+            "homepage": "https://github.com/MarkBaker/PHPComplex",
+            "keywords": [
+                "complex",
+                "mathematics"
+            ],
+            "support": {
+                "issues": "https://github.com/MarkBaker/PHPComplex/issues",
+                "source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2"
+            },
+            "time": "2022-12-06T16:21:08+00:00"
+        },
+        {
+            "name": "markbaker/matrix",
+            "version": "3.0.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/MarkBaker/PHPMatrix.git",
+                "reference": "728434227fe21be27ff6d86621a1b13107a2562c"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c",
+                "reference": "728434227fe21be27ff6d86621a1b13107a2562c",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1 || ^8.0"
+            },
+            "require-dev": {
+                "dealerdirect/phpcodesniffer-composer-installer": "dev-master",
+                "phpcompatibility/php-compatibility": "^9.3",
+                "phpdocumentor/phpdocumentor": "2.*",
+                "phploc/phploc": "^4.0",
+                "phpmd/phpmd": "2.*",
+                "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
+                "sebastian/phpcpd": "^4.0",
+                "squizlabs/php_codesniffer": "^3.7"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Matrix\\": "classes/src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Mark Baker",
+                    "email": "mark@demon-angel.eu"
+                }
+            ],
+            "description": "PHP Class for working with matrices",
+            "homepage": "https://github.com/MarkBaker/PHPMatrix",
+            "keywords": [
+                "mathematics",
+                "matrix",
+                "vector"
+            ],
+            "support": {
+                "issues": "https://github.com/MarkBaker/PHPMatrix/issues",
+                "source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1"
+            },
+            "time": "2022-12-02T22:17:43+00:00"
+        },
+        {
+            "name": "masterminds/html5",
+            "version": "2.8.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/Masterminds/html5-php.git",
+                "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf",
+                "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf",
+                "shasum": ""
+            },
+            "require": {
+                "ext-dom": "*",
+                "php": ">=5.3.0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "2.7-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Masterminds\\": "src"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Matt Butcher",
+                    "email": "technosophos@gmail.com"
+                },
+                {
+                    "name": "Matt Farina",
+                    "email": "matt@mattfarina.com"
+                },
+                {
+                    "name": "Asmir Mustafic",
+                    "email": "goetas@gmail.com"
+                }
+            ],
+            "description": "An HTML5 parser and serializer.",
+            "homepage": "http://masterminds.github.io/html5-php",
+            "keywords": [
+                "HTML5",
+                "dom",
+                "html",
+                "parser",
+                "querypath",
+                "serializer",
+                "xml"
+            ],
+            "support": {
+                "issues": "https://github.com/Masterminds/html5-php/issues",
+                "source": "https://github.com/Masterminds/html5-php/tree/2.8.1"
+            },
+            "time": "2023-05-10T11:58:31+00:00"
+        },
         {
             "name": "monolog/monolog",
             "version": "2.9.1",
@@ -2305,19 +2699,214 @@
             },
             "funding": [
                 {
-                    "url": "https://www.paypal.com/paypalme/enunomaduro",
-                    "type": "custom"
+                    "url": "https://www.paypal.com/paypalme/enunomaduro",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/nunomaduro",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/xiCO2k",
+                    "type": "github"
+                }
+            ],
+            "time": "2023-02-08T01:06:31+00:00"
+        },
+        {
+            "name": "phenx/php-font-lib",
+            "version": "0.5.6",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/dompdf/php-font-lib.git",
+                "reference": "a1681e9793040740a405ac5b189275059e2a9863"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/a1681e9793040740a405ac5b189275059e2a9863",
+                "reference": "a1681e9793040740a405ac5b189275059e2a9863",
+                "shasum": ""
+            },
+            "require": {
+                "ext-mbstring": "*"
+            },
+            "require-dev": {
+                "symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "FontLib\\": "src/FontLib"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "LGPL-2.1-or-later"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Ménager",
+                    "email": "fabien.menager@gmail.com"
+                }
+            ],
+            "description": "A library to read, parse, export and make subsets of different types of font files.",
+            "homepage": "https://github.com/PhenX/php-font-lib",
+            "support": {
+                "issues": "https://github.com/dompdf/php-font-lib/issues",
+                "source": "https://github.com/dompdf/php-font-lib/tree/0.5.6"
+            },
+            "time": "2024-01-29T14:45:26+00:00"
+        },
+        {
+            "name": "phenx/php-svg-lib",
+            "version": "0.5.3",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/dompdf/php-svg-lib.git",
+                "reference": "0e46722c154726a5f9ac218197ccc28adba16fcf"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/0e46722c154726a5f9ac218197ccc28adba16fcf",
+                "reference": "0e46722c154726a5f9ac218197ccc28adba16fcf",
+                "shasum": ""
+            },
+            "require": {
+                "ext-mbstring": "*",
+                "php": "^7.1 || ^8.0",
+                "sabberworm/php-css-parser": "^8.4"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Svg\\": "src/Svg"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "LGPL-3.0-or-later"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Ménager",
+                    "email": "fabien.menager@gmail.com"
+                }
+            ],
+            "description": "A library to read, parse and export to PDF SVG files.",
+            "homepage": "https://github.com/PhenX/php-svg-lib",
+            "support": {
+                "issues": "https://github.com/dompdf/php-svg-lib/issues",
+                "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.3"
+            },
+            "time": "2024-02-23T20:39:24+00:00"
+        },
+        {
+            "name": "phpoffice/phpspreadsheet",
+            "version": "2.0.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
+                "reference": "4a77798f835119754961a97714f135826a323caa"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/4a77798f835119754961a97714f135826a323caa",
+                "reference": "4a77798f835119754961a97714f135826a323caa",
+                "shasum": ""
+            },
+            "require": {
+                "ext-ctype": "*",
+                "ext-dom": "*",
+                "ext-fileinfo": "*",
+                "ext-gd": "*",
+                "ext-iconv": "*",
+                "ext-libxml": "*",
+                "ext-mbstring": "*",
+                "ext-simplexml": "*",
+                "ext-xml": "*",
+                "ext-xmlreader": "*",
+                "ext-xmlwriter": "*",
+                "ext-zip": "*",
+                "ext-zlib": "*",
+                "maennchen/zipstream-php": "^2.1 || ^3.0",
+                "markbaker/complex": "^3.0",
+                "markbaker/matrix": "^3.0",
+                "php": "^8.0",
+                "psr/http-client": "^1.0",
+                "psr/http-factory": "^1.0",
+                "psr/simple-cache": "^1.0 || ^2.0 || ^3.0",
+                "voku/anti-xss": "^4.1"
+            },
+            "require-dev": {
+                "dealerdirect/phpcodesniffer-composer-installer": "dev-main",
+                "dompdf/dompdf": "^2.0",
+                "friendsofphp/php-cs-fixer": "^3.2",
+                "mitoteam/jpgraph": "^10.3",
+                "mpdf/mpdf": "^8.1.1",
+                "phpcompatibility/php-compatibility": "^9.3",
+                "phpstan/phpstan": "^1.1",
+                "phpstan/phpstan-phpunit": "^1.0",
+                "phpunit/phpunit": "^9.6",
+                "squizlabs/php_codesniffer": "^3.7",
+                "tecnickcom/tcpdf": "^6.5"
+            },
+            "suggest": {
+                "dompdf/dompdf": "Option for rendering PDF with PDF Writer",
+                "ext-intl": "PHP Internationalization Functions",
+                "mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
+                "mpdf/mpdf": "Option for rendering PDF with PDF Writer",
+                "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Maarten Balliauw",
+                    "homepage": "https://blog.maartenballiauw.be"
+                },
+                {
+                    "name": "Mark Baker",
+                    "homepage": "https://markbakeruk.net"
                 },
                 {
-                    "url": "https://github.com/nunomaduro",
-                    "type": "github"
+                    "name": "Franck Lefevre",
+                    "homepage": "https://rootslabs.net"
                 },
                 {
-                    "url": "https://github.com/xiCO2k",
-                    "type": "github"
+                    "name": "Erik Tilt"
+                },
+                {
+                    "name": "Adrien Crivelli"
                 }
             ],
-            "time": "2023-02-08T01:06:31+00:00"
+            "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
+            "homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
+            "keywords": [
+                "OpenXML",
+                "excel",
+                "gnumeric",
+                "ods",
+                "php",
+                "spreadsheet",
+                "xls",
+                "xlsx"
+            ],
+            "support": {
+                "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
+                "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/2.0.0"
+            },
+            "time": "2024-01-24T10:41:42+00:00"
         },
         {
             "name": "phpoption/phpoption",
@@ -3060,6 +3649,71 @@
             ],
             "time": "2023-01-12T18:13:24+00:00"
         },
+        {
+            "name": "sabberworm/php-css-parser",
+            "version": "v8.5.1",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git",
+                "reference": "4a3d572b0f8b28bb6fd016ae8bbfc445facef152"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/4a3d572b0f8b28bb6fd016ae8bbfc445facef152",
+                "reference": "4a3d572b0f8b28bb6fd016ae8bbfc445facef152",
+                "shasum": ""
+            },
+            "require": {
+                "ext-iconv": "*",
+                "php": ">=5.6.20"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "^5.7.27"
+            },
+            "suggest": {
+                "ext-mbstring": "for parsing UTF-8 CSS"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-main": "9.0.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Sabberworm\\CSS\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Raphael Schweikert"
+                },
+                {
+                    "name": "Oliver Klee",
+                    "email": "github@oliverklee.de"
+                },
+                {
+                    "name": "Jake Hotson",
+                    "email": "jake.github@qzdesign.co.uk"
+                }
+            ],
+            "description": "Parser for CSS Files written in PHP",
+            "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser",
+            "keywords": [
+                "css",
+                "parser",
+                "stylesheet"
+            ],
+            "support": {
+                "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues",
+                "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.5.1"
+            },
+            "time": "2024-02-15T16:41:13+00:00"
+        },
         {
             "name": "symfony/console",
             "version": "v6.0.19",
@@ -4003,6 +4657,86 @@
             ],
             "time": "2022-11-03T14:55:06+00:00"
         },
+        {
+            "name": "symfony/polyfill-iconv",
+            "version": "v1.29.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/polyfill-iconv.git",
+                "reference": "cd4226d140ecd3d0f13d32ed0a4a095ffe871d2f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/cd4226d140ecd3d0f13d32ed0a4a095ffe871d2f",
+                "reference": "cd4226d140ecd3d0f13d32ed0a4a095ffe871d2f",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.1"
+            },
+            "provide": {
+                "ext-iconv": "*"
+            },
+            "suggest": {
+                "ext-iconv": "For best performance"
+            },
+            "type": "library",
+            "extra": {
+                "thanks": {
+                    "name": "symfony/polyfill",
+                    "url": "https://github.com/symfony/polyfill"
+                }
+            },
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "Symfony\\Polyfill\\Iconv\\": ""
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony polyfill for the Iconv extension",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "compatibility",
+                "iconv",
+                "polyfill",
+                "portable",
+                "shim"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/polyfill-iconv/tree/v1.29.0"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-01-29T20:11:03+00:00"
+        },
         {
             "name": "symfony/polyfill-intl-grapheme",
             "version": "v1.27.0",
@@ -5446,6 +6180,89 @@
             ],
             "time": "2022-10-16T01:01:54+00:00"
         },
+        {
+            "name": "voku/anti-xss",
+            "version": "4.1.42",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/voku/anti-xss.git",
+                "reference": "bca1f8607e55a3c5077483615cd93bd8f11bd675"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/voku/anti-xss/zipball/bca1f8607e55a3c5077483615cd93bd8f11bd675",
+                "reference": "bca1f8607e55a3c5077483615cd93bd8f11bd675",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.0.0",
+                "voku/portable-utf8": "~6.0.2"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.1.x-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "voku\\helper\\": "src/voku/helper/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "EllisLab Dev Team",
+                    "homepage": "http://ellislab.com/"
+                },
+                {
+                    "name": "Lars Moelleken",
+                    "email": "lars@moelleken.org",
+                    "homepage": "https://www.moelleken.org/"
+                }
+            ],
+            "description": "anti xss-library",
+            "homepage": "https://github.com/voku/anti-xss",
+            "keywords": [
+                "anti-xss",
+                "clean",
+                "security",
+                "xss"
+            ],
+            "support": {
+                "issues": "https://github.com/voku/anti-xss/issues",
+                "source": "https://github.com/voku/anti-xss/tree/4.1.42"
+            },
+            "funding": [
+                {
+                    "url": "https://www.paypal.me/moelleken",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/voku",
+                    "type": "github"
+                },
+                {
+                    "url": "https://opencollective.com/anti-xss",
+                    "type": "open_collective"
+                },
+                {
+                    "url": "https://www.patreon.com/voku",
+                    "type": "patreon"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/voku/anti-xss",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2023-07-03T14:40:46+00:00"
+        },
         {
             "name": "voku/portable-ascii",
             "version": "2.0.1",
@@ -5520,6 +6337,109 @@
             ],
             "time": "2022-03-08T17:03:00+00:00"
         },
+        {
+            "name": "voku/portable-utf8",
+            "version": "6.0.13",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/voku/portable-utf8.git",
+                "reference": "b8ce36bf26593e5c2e81b1850ef0ffb299d2043f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/voku/portable-utf8/zipball/b8ce36bf26593e5c2e81b1850ef0ffb299d2043f",
+                "reference": "b8ce36bf26593e5c2e81b1850ef0ffb299d2043f",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=7.0.0",
+                "symfony/polyfill-iconv": "~1.0",
+                "symfony/polyfill-intl-grapheme": "~1.0",
+                "symfony/polyfill-intl-normalizer": "~1.0",
+                "symfony/polyfill-mbstring": "~1.0",
+                "symfony/polyfill-php72": "~1.0",
+                "voku/portable-ascii": "~2.0.0"
+            },
+            "require-dev": {
+                "phpstan/phpstan": "1.9.*@dev",
+                "phpstan/phpstan-strict-rules": "1.4.*@dev",
+                "phpunit/phpunit": "~6.0 || ~7.0 || ~9.0",
+                "thecodingmachine/phpstan-strict-rules": "1.0.*@dev",
+                "voku/phpstan-rules": "3.1.*@dev"
+            },
+            "suggest": {
+                "ext-ctype": "Use Ctype for e.g. hexadecimal digit detection",
+                "ext-fileinfo": "Use Fileinfo for better binary file detection",
+                "ext-iconv": "Use iconv for best performance",
+                "ext-intl": "Use Intl for best performance",
+                "ext-json": "Use JSON for string detection",
+                "ext-mbstring": "Use Mbstring for best performance"
+            },
+            "type": "library",
+            "autoload": {
+                "files": [
+                    "bootstrap.php"
+                ],
+                "psr-4": {
+                    "voku\\": "src/voku/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "(Apache-2.0 or GPL-2.0)"
+            ],
+            "authors": [
+                {
+                    "name": "Nicolas Grekas",
+                    "email": "p@tchwork.com"
+                },
+                {
+                    "name": "Hamid Sarfraz",
+                    "homepage": "http://pageconfig.com/"
+                },
+                {
+                    "name": "Lars Moelleken",
+                    "homepage": "http://www.moelleken.org/"
+                }
+            ],
+            "description": "Portable UTF-8 library - performance optimized (unicode) string functions for php.",
+            "homepage": "https://github.com/voku/portable-utf8",
+            "keywords": [
+                "UTF",
+                "clean",
+                "php",
+                "unicode",
+                "utf-8",
+                "utf8"
+            ],
+            "support": {
+                "issues": "https://github.com/voku/portable-utf8/issues",
+                "source": "https://github.com/voku/portable-utf8/tree/6.0.13"
+            },
+            "funding": [
+                {
+                    "url": "https://www.paypal.me/moelleken",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/voku",
+                    "type": "github"
+                },
+                {
+                    "url": "https://opencollective.com/portable-utf8",
+                    "type": "open_collective"
+                },
+                {
+                    "url": "https://www.patreon.com/voku",
+                    "type": "patreon"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/voku/portable-utf8",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2023-03-08T08:35:38+00:00"
+        },
         {
             "name": "webmozart/assert",
             "version": "1.11.0",
@@ -8114,5 +9034,5 @@
         "php": "^8.0.2"
     },
     "platform-dev": [],
-    "plugin-api-version": "2.0.0"
+    "plugin-api-version": "2.3.0"
 }

+ 183 - 0
public/assets/js/aCollapTable.js

@@ -0,0 +1,183 @@
+/*
+ * jQuery Alvaro's Collaptable 1.0.2
+ *
+ * Copyright (c) 2010 Alvaro Véliz Marín - yo@alvaroveliz.cl
+ *
+ * Licensed under the MIT license:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *
+ * More info in http://github.com/alvaroveliz/aCollapTable
+ */
+(function($){
+  $.fn.extend({
+    aCollapTable: function(options) {
+      var defaults = {
+        startCollapsed : true,
+        addColumn: true,
+        plusButton: '+',
+        minusButton: '-'
+      };
+      var options = $.extend(defaults, options);
+      var self = this;
+      var parents = [];
+
+      var _collaptable = function($element, $parent, $display)
+      {
+        parent = (typeof($parent) == 'undefined') ? $element.parents('tr').data('id') : $parent;
+        display = (typeof($display) == 'undefined') ? ( ($element.hasClass('act-expanded')) ? 'none' : 'table-row' ) : $display;
+        table = self;
+
+        $('tr[data-parent='+parent+']', table).each(function(key, item){
+          $(item).css('display', display);
+          if ($(item).hasClass('act-tr-expanded')) {
+            _collaptable($element, $(item).data('id'), display);
+          }
+        });
+
+        spacer = _getSpacer($element.parents('tr'));
+
+        if (display == 'none') {
+          $element.html(spacer + options.plusButton).removeClass('act-expanded').addClass('act-collapsed');
+          $element.parents('tr').addClass('act-tr-collapsed').removeClass('act-tr-expanded');
+        }
+        else {
+          $element.html(spacer + options.minusButton).removeClass('act-collapsed').addClass('act-expanded');
+          $element.parents('tr').addClass('act-tr-expanded').removeClass('act-tr-collapsed');
+        }
+      };
+
+      var _levelsAndParents = function(obj)
+      {
+        $('tr', obj).each(function(k, item){
+          if ($(item).data('id')) {
+            parent = { id : $(item).data('id'), parent : $(item).data('parent') };
+            parents.push(parent);
+          }
+        });
+
+        $('tr', obj).each(function(k, item){
+          if ($(item).data('id')) {
+            level = _getLevel($(item));
+            $(item).attr('data-level', level);
+          }
+        });
+      };
+
+      var _getLevel = function($item, $level)
+      {
+        $level = (typeof($level) == 'undefined') ? 0 : $level;
+        if ( $item.data('parent') == '' ) {
+          return $level;
+        }
+        else {
+          $parent = $('tr[data-id='+$item.data('parent')+']');
+          return _getLevel($parent, $level+1);
+        }
+      };
+
+      var _getSpacer = function($item)
+      {
+        spacer = '';
+        for (i = 0; i < $item.data('level') ; i++) {
+          spacer += '&nbsp;&nbsp;';
+        }
+        return spacer;
+      };
+
+      var _bindButtons = function()
+      {
+        $(document).on('click', '.act-button-expand', function(){
+          if ( $('tr', self).length > 0 ) {
+            expands = [];
+            $('tr', self).each(function(k, item){
+              if ($(item).hasClass('act-tr-collapsed') && $(item).css('display') != 'none') {
+                expands.push($(item));
+              }
+            });
+            $.each(expands, function(k, $item){
+              _collaptable($('.act-more', $item));
+            });
+          }
+        });
+
+        $(document).on('click', '.act-button-collapse', function(){
+          if ( $('tr', self).length > 0 ) {
+
+          }
+        });
+
+        $(document).on('click', '.act-button-expand-all', function(){
+          if ( $('tr', self).length > 0 ) {
+            collapseds = [];
+          $('tr', self).each(function(k, item){
+              if ($(item).hasClass('act-tr-collapsed')) {
+                _collaptable($('.act-more', $(item)));
+            }
+          });
+          }
+        });
+
+        $(document).on('click', '.act-button-collapse-all', function(){
+          if ( $('tr', self).length > 0 ) {
+            collapseds = [];
+            $('tr', self).each(function(k, item){
+              if ($(item).hasClass('act-tr-expanded')) {
+                _collaptable($('.act-more', $(item)));
+              }
+            });
+          }
+        });
+
+      }
+
+      return this.each(function() {
+        var o = options;
+        var obj = $(this);
+        _levelsAndParents(obj);
+        _bindButtons();
+
+        // adding minus
+        if ( $('tr', obj).length > 0) {
+          $('tr', obj).each(function(k, item){
+            spacer = _getSpacer($(item));
+
+            $minus = $('<a />').attr('href', 'javascript:void(0)')
+              .addClass('act-more act-expanded')
+              .html(spacer + o.minusButton)
+              .bind('click', function(){
+                _collaptable($(this));
+              })
+              ;
+
+            if ($('tr[data-parent='+$(item).data('id')+']').length > 0) {
+              $button = (o.addColumn == true) ? $('<td />').html($minus) : $minus;
+              itemClass = (o.startCollapsed) ? 'act-tr-collapsed' : 'act-tr-expanded';
+              $(item).addClass(itemClass);
+            }
+            else {
+              $button = (o.addColumn == true) ? $('<td />').html(spacer+'&nbsp;&nbsp;') : spacer+'&nbsp;&nbsp;';
+            }
+
+            if (o.addColumn == true) {
+              $(item).prepend($button);
+            }
+            else {
+              $(item).children(':first').prepend($button);
+            }
+
+            // level class
+            $(item).addClass('act-tr-level-'+$(item).data('level'));
+          });
+
+          // start collapsed
+          if (o.startCollapsed) {
+            $('.act-more').each(function(k, item){
+              $(item).click();
+            });
+          }
+        }
+      });
+    }
+  });
+
+})(jQuery);

+ 90 - 0
public/assets/js/multiple_select.js

@@ -0,0 +1,90 @@
+ $(document).ready(function () {
+            $(document).on("click", ".MultiCheckBox", function () {
+                var detail = $(this).next();
+                detail.show();
+            });
+
+            $(document).on("click", ".MultiCheckBoxDetailHeader input", function (e) {
+                e.stopPropagation();
+                var hc = $(this).prop("checked");
+                $(this).closest(".MultiCheckBoxDetail").find(".MultiCheckBoxDetailBody input").prop("checked", hc);
+                $(this).closest(".MultiCheckBoxDetail").next().UpdateSelect();
+            });
+
+            $(document).on("click", ".MultiCheckBoxDetailHeader", function (e) {
+                var inp = $(this).find("input");
+                var chk = inp.prop("checked");
+                inp.prop("checked", !chk);
+                $(this).closest(".MultiCheckBoxDetail").find(".MultiCheckBoxDetailBody input").prop("checked", !chk);
+                $(this).closest(".MultiCheckBoxDetail").next().UpdateSelect();
+            });
+
+            $(document).on("click", ".MultiCheckBoxDetail .cont input", function (e) {
+                e.stopPropagation();
+                $(this).closest(".MultiCheckBoxDetail").next().UpdateSelect();
+
+                var val = ($(".MultiCheckBoxDetailBody input:checked").length == $(".MultiCheckBoxDetailBody input").length)
+                $(".MultiCheckBoxDetailHeader input").prop("checked", val);
+            });
+
+            $(document).on("click", ".MultiCheckBoxDetail .cont", function (e) {
+                var inp = $(this).find("input");
+                var chk = inp.prop("checked");
+                inp.prop("checked", !chk);
+
+                var multiCheckBoxDetail = $(this).closest(".MultiCheckBoxDetail");
+                var multiCheckBoxDetailBody = $(this).closest(".MultiCheckBoxDetailBody");
+                multiCheckBoxDetail.next().UpdateSelect();
+
+                var val = ($(".MultiCheckBoxDetailBody input:checked").length == $(".MultiCheckBoxDetailBody input").length)
+                $(".MultiCheckBoxDetailHeader input").prop("checked", val);
+            });
+
+            $(document).mouseup(function (e) {
+                var container = $(".MultiCheckBoxDetail");
+                if (!container.is(e.target) && container.has(e.target).length === 0) {
+                    container.hide();
+                }
+            });
+        });
+
+        var defaultMultiCheckBoxOption = { width: '220px', defaultText: 'Select Below', height: '200px' };
+
+        jQuery.fn.extend({
+            CreateMultiCheckBox: function (options) {
+
+                var localOption = {};
+                localOption.width = (options != null && options.width != null && options.width != undefined) ? options.width : defaultMultiCheckBoxOption.width;
+                localOption.defaultText = (options != null && options.defaultText != null && options.defaultText != undefined) ? options.defaultText : defaultMultiCheckBoxOption.defaultText;
+                localOption.height = (options != null && options.height != null && options.height != undefined) ? options.height : defaultMultiCheckBoxOption.height;
+
+                this.hide();
+                this.attr("multiple", "multiple");
+                var divSel = $("<div class='MultiCheckBox'>" + localOption.defaultText + "<span class='k-icon k-i-arrow-60-down'><svg aria-hidden='true' focusable='false' data-prefix='fas' data-icon='sort-down' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512' class='svg-inline--fa fa-sort-down fa-w-10 fa-2x'><path fill='currentColor' d='M41 288h238c21.4 0 32.1 25.9 17 41L177 448c-9.4 9.4-24.6 9.4-33.9 0L24 329c-15.1-15.1-4.4-41 17-41z' class=''></path></svg></span></div>").insertBefore(this);
+                divSel.css({ "width": localOption.width });
+
+                var detail = $("<div class='MultiCheckBoxDetail'><div class='MultiCheckBoxDetailHeader'><input type='checkbox' class='mulinput' value='-1982' /><div>Select All</div></div><div class='MultiCheckBoxDetailBody'></div></div>").insertAfter(divSel);
+                detail.css({ "width": parseInt(options.width) + 10, "max-height": localOption.height });
+                var multiCheckBoxDetailBody = detail.find(".MultiCheckBoxDetailBody");
+
+                this.find("option").each(function () {
+                    var val = $(this).attr("value");
+
+                    if (val == undefined)
+                        val = '';
+
+                    multiCheckBoxDetailBody.append("<div class='cont'><div><input type='checkbox' class='mulinput' value='" + val + "' /></div><div>" + $(this).text() + "</div></div>");
+                });
+
+                multiCheckBoxDetailBody.css("max-height", (parseInt($(".MultiCheckBoxDetail").css("max-height")) - 28) + "px");
+            },
+            UpdateSelect: function () {
+                var arr = [];
+
+                this.prev().find(".mulinput:checked").each(function () {
+                    arr.push($(this).val());
+                });
+
+                this.val(arr);
+            },
+        });

+ 8 - 0
resources/views/layouts/app.blade.php

@@ -10,6 +10,14 @@
   <link rel="stylesheet" href="/css/style.css">
 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
   @livewireStyles
+  <style>
+  .page-link.active, .active > .page-link
+  {
+
+    background-color: #006099 !important;
+    border-color: var(--bs-pagination-active-border-color);
+  }
+  </style>
 
 </head>
 

+ 3 - 3
resources/views/livewire/categories.blade.php

@@ -1,6 +1,6 @@
 <div class="row">
     <div class="col-md-4">
-        <div class="tessera--added d-flex align-items-center justify-content-between mt-4 mb-3">
+        <div class="tessera--added d-flex align-items-center justify-content-between">
             <select id="level_1_id" class="form-select" aria-label="Gruppo" wire:model="level_1_id" style="width:100%;">
                 <option value="">--Seleziona--
                 @foreach($level_1 as $l1)
@@ -11,7 +11,7 @@
     </div>
     @if(count($level_2) > 0)
         <div class="col-md-4">
-            <div class="tessera--added d-flex align-items-center justify-content-between mt-4 mb-3">
+            <div class="tessera--added d-flex align-items-center justify-content-between">
                 <select id="level_2_id" class="form-select" aria-label="Gruppo" wire:model="level_2_id" style="width:100%;">
                     <option value="">--Seleziona--
                     @foreach($level_2 as $l2)
@@ -23,7 +23,7 @@
     @endif
     @if(count($level_3) > 0)
         <div class="col-md-4">
-            <div class="tessera--added d-flex align-items-center justify-content-between mt-4 mb-3">
+            <div class="tessera--added d-flex align-items-center justify-content-between">
                 <select id="level_3_id" class="form-select" aria-label="Gruppo" wire:model="level_3_id" style="width:100%;">
                     <option value="">--Seleziona--
                     @foreach($level_3 as $l3)

+ 0 - 7
resources/views/livewire/causal.blade.php

@@ -120,13 +120,6 @@
                             </div>
                         </div>
 
-                        <div class="form--item mb-3">
-                            <div class="form-check form-check-inline">
-                                <input class="form-check-input" type="checkbox" id="course" wire:model="course">
-                                <label class="form-check-label" for="course">E' un corso</label>
-                            </div>
-                        </div>
-
                         <!-- // inline input field -->
 
                         <div class="form--item">

+ 3 - 3
resources/views/livewire/causals.blade.php

@@ -1,6 +1,6 @@
 <div class="row">
     <div class="col-md-4">
-        <div class="tessera--added d-flex align-items-center justify-content-between mt-4 mb-3">
+        <div class="tessera--added d-flex align-items-center justify-content-between">
             <select id="level_1_id" class="form-select" aria-label="Gruppo" wire:model="level_1_id" style="width:100%;">
                 <option value="">--Seleziona--
                 @foreach($level_1 as $l1)
@@ -11,7 +11,7 @@
     </div>
     @if(count($level_2) > 0)
         <div class="col-md-4">
-            <div class="tessera--added d-flex align-items-center justify-content-between mt-4 mb-3">
+            <div class="tessera--added d-flex align-items-center justify-content-between">
                 <select id="level_2_id" class="form-select" aria-label="Gruppo" wire:model="level_2_id" style="width:100%;">
                     <option value="">--Seleziona--
                     @foreach($level_2 as $l2)
@@ -23,7 +23,7 @@
     @endif
     @if(count($level_3) > 0)
         <div class="col-md-4">
-            <div class="tessera--added d-flex align-items-center justify-content-between mt-4 mb-3">
+            <div class="tessera--added d-flex align-items-center justify-content-between">
                 <select id="level_3_id" class="form-select" aria-label="Gruppo" wire:model="level_3_id" style="width:100%;">
                     <option value="">--Seleziona--
                     @foreach($level_3 as $l3)

+ 36 - 0
resources/views/livewire/courses.blade.php

@@ -0,0 +1,36 @@
+<div class="row">
+    <div class="col-md-4">
+        <div class="tessera--added d-flex align-items-center justify-content-between">
+            <select id="level_1_id" class="form-select" aria-label="Gruppo" wire:model="level_1_id" style="width:100%;">
+                <option value="">--Seleziona--
+                @foreach($level_1 as $l1)
+                    <option value="{{$l1["id"]}}">{{$l1["name"]}}
+                @endforeach
+            </select>
+        </div>
+    </div>
+    @if(count($level_2) > 0)
+        <div class="col-md-4">
+            <div class="tessera--added d-flex align-items-center justify-content-between">
+                <select id="level_2_id" class="form-select" aria-label="Gruppo" wire:model="level_2_id" style="width:100%;">
+                    <option value="">--Seleziona--
+                    @foreach($level_2 as $l2)
+                        <option value="{{$l2["id"]}}">{{$l2["name"]}}
+                    @endforeach
+                </select>
+            </div>
+        </div>
+    @endif
+    @if(count($level_3) > 0)
+        <div class="col-md-4">
+            <div class="tessera--added d-flex align-items-center justify-content-between">
+                <select id="level_3_id" class="form-select" aria-label="Gruppo" wire:model="level_3_id" style="width:100%;">
+                    <option value="">--Seleziona--
+                    @foreach($level_3 as $l3)
+                        <option value="{{$l3["id"]}}">{{$l3["name"]}}
+                    @endforeach
+                </select>
+            </div>
+        </div>
+    @endif
+</div>

+ 67 - 75
resources/views/livewire/member.blade.php

@@ -185,7 +185,7 @@
 
         @else
 
-        <div class="col-auto filterWrapper" id="filter--section">
+        <div class="col-auto filterWrapper" id="filter--section" wire:ignore.self>
             <aside>
                 <header>
                     <h2>Filtra Utenti</h2>
@@ -200,22 +200,11 @@
                             <div class="col-12">
                                 @foreach(getCards() as $card)
                                     <div class="form-check form-check-inline d-inline-flex align-items-center">
-                                        <input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option1">
-                                        <label class="form-check-label ms-2" for="inlineCheckbox1">{{$card->name}}</label>
+                                        <input class="form-check-input" type="checkbox" value="{{$card->id}}" wire:model="filterCard">
+                                        <label class="form-check-label ms-2" >{{$card->name}}</label>
                                     </div>
                                 @endforeach
                             </div>
-                            <!--<div class="col-6">
-                                <div class="form-check form-check-inline d-inline-flex align-items-center">
-                                    <input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option4">
-                                    <label class="form-check-label ms-2" for="inlineCheckbox1">Uisp</label>
-                                </div>
-                                <div class="form-check form-check-inline d-inline-flex align-items-center">
-                                    <input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option5">
-                                    <label class="form-check-label ms-2" for="inlineCheckbox1">Csi</label>
-                                </div>
-
-                            </div>-->
                         </div>
                     </div>
                     <!-- filter item -->
@@ -226,22 +215,22 @@
                         <div class="filter--item_formElement row">
                             <div class="col-6">
                                 <div class="form-check form-check-inline d-inline-flex align-items-center">
-                                    <input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option1">
-                                    <label class="form-check-label ms-2" for="inlineCheckbox1">Normale</label>
+                                    <input class="form-check-input" type="checkbox"  wire:model="filterCertNormal">
+                                    <label class="form-check-label ms-2" >Normale</label>
                                 </div>
                                 <div class="form-check form-check-inline d-inline-flex align-items-center">
-                                    <input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option2">
-                                    <label class="form-check-label ms-2" for="inlineCheckbox1">In Scadenza</label>
+                                    <input class="form-check-input" type="checkbox"  wire:model="filterCertInScadenza">
+                                    <label class="form-check-label ms-2" >In Scadenza</label>
                                 </div>
                             </div>
                             <div class="col-6">
                                 <div class="form-check form-check-inline d-inline-flex align-items-center">
-                                    <input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option4">
-                                    <label class="form-check-label ms-2" for="inlineCheckbox1">Agonistico</label>
+                                    <input class="form-check-input" type="checkbox"  wire:model="filterCertAgonistic">
+                                    <label class="form-check-label ms-2" >Agonistico</label>
                                 </div>
                                 <div class="form-check form-check-inline d-inline-flex align-items-center">
-                                    <input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option5">
-                                    <label class="form-check-label ms-2" for="inlineCheckbox1">Scaduti</label>
+                                    <input class="form-check-input" type="checkbox"  wire:model="filterCertScaduto">
+                                    <label class="form-check-label ms-2" >Scaduti</label>
                                 </div>
 
                             </div>
@@ -256,8 +245,8 @@
                             <div class="col-6">
                                 @foreach(getCategories() as $category)
                                     <div class="form-check form-check-inline d-inline-flex align-items-center">
-                                        <input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option1">
-                                        <label class="form-check-label ms-2" for="inlineCheckbox1">{{$category->name}}</label>
+                                        <input class="form-check-input" type="checkbox"  value="{{$category->id}}" wire:model="filterCategory">
+                                        <label class="form-check-label ms-2" >{{$category->name}}</label>
                                     </div>
                                 @endforeach
 
@@ -267,33 +256,13 @@
                     </div>
                     <!-- filter item -->
 
-                    <div class="filter--item">
-                        <span class="filter--item_title">Stato Pagamenti</span>
 
 
-
-                        <div class="filter--item_formElement row">
-                            <div class="col-6">
-                                <div class="form-check form-check-inline d-inline-flex align-items-center">
-                                    <input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option1">
-                                    <label class="form-check-label ms-2" for="inlineCheckbox1">Attivi</label>
-                                </div>
-                            </div>
-                            <div class="col-6">
-                                <div class="form-check form-check-inline d-inline-flex align-items-center">
-                                    <input class="form-check-input" type="checkbox" id="inlineCheckbox1" value="option4">
-                                    <label class="form-check-label ms-2" for="inlineCheckbox1">Scaduti</label>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-                    <!-- filter item -->
-
                 </form>
 
                 <footer>
                     <div class="filter--buttons d-flex align-items-center justify-content-between">
-                        <button class="btn--ui small dark disable">cancella</button><button class="btn--ui small white" wire:click="advancedSearch()">filtra</button>
+                        <button class="btn--ui small dark disable"  wire:click.prevent="advancedSearchCancel()">cancella</button><button class="btn--ui small white" wire:click.prevent="advancedSearch()">filtra</button>
                     </div>
                 </footer>
 
@@ -354,21 +323,23 @@
                             <tr>
                                 <!--<th scope="col"><label><input class="table-check" type="checkbox" data-tablesaw-checkall=""></th>-->
                                 <th scope="col"><input class="table-check" type="checkbox" wire:model="checkedAll"  wire:click="checkUncheckAll()"></th>
+                                <th scope="col">#</th>
                                 <th scope="col" wire:click.prevent="sortBy('id')" style="cursor:pointer">Codice&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
                                 <th scope="col" wire:click.prevent="sortBy('last_name')" style="cursor:pointer">Cognome&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
                                 <th scope="col" wire:click.prevent="sortBy('first_name')" style="cursor:pointer">Nome&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
                                 <th scope="col" wire:click.prevent="sortBy('email')" style="cursor:pointer">Email&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
-                                <th scope="col" wire:click.prevent="sortBy('age')" style="cursor:pointer">Età (anni)&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
-                                <th scope="col" wire:click.prevent="sortBy('state')" style="cursor:pointer">Stato&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
-                                <th scope="col" wire:click.prevent="sortBy('status')" style="cursor:pointer">Stato tesseramento&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
-                                <th scope="col" wire:click.prevent="sortBy('certificate')" style="cursor:pointer">Certificato&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
+                                <th scope="col">Età (anni)</th>
+                                <th scope="col">Stato</th>
+                                <th scope="col">Stato tesseramento</th>
+                                <th scope="col">Certificato</th>
                                 <th scope="col">...</th>
                             </tr>
                         </thead>
                         <tbody id="checkall-target">
-                            @foreach($records as $record)
+                            @foreach($datas as $idx => $record)
                                 <tr>
                                     <td> <label><input class="table-check" type="checkbox" wire:model="multipleIds" value="{{$record->id}}"><span class="sr-only d-inline-block d-lg-none ms-2 mobile-row-selector"> Seleziona riga</span></label></td>
+                                    <td>{{ ($idx + 1) + (($datas->currentPage() - 1) * $datas->perPage()) }}</td>
                                     <td>ID{{str_pad($record->id, 5, "0", STR_PAD_LEFT)}}</td>
                                     <td><a href="#" wire:click="showDetail({{$record->id}})">{{$record->last_name}}</a></td>
                                     <td><a href="#" wire:click="showDetail({{$record->id}})">{{$record->first_name}}</a></td>
@@ -394,22 +365,24 @@
                                     $has_certificate = $record->hasCertificate();
                                     @endphp
                                     <td>
-                                        <b class=" tablesaw-cell-label">Scadenza certificato</b>
-                                        <span class="tablesaw-cell-content d-flex align-items-center">
-                                            @if($has_certificate["date"] < date("Y-m-d"))
-                                                <i class="ico--ui check suspended me-2"></i>
-                                                Scaduto :
-                                            @endif
-                                            @if($has_certificate["date"] >= date("Y-m-d") && $has_certificate["date"] < date("Y-m-d", strtotime("+1 month")))
-                                                <i class="ico--ui check due me-2"></i>
-                                                In scadenza :
-                                            @endif
-                                            @if($has_certificate["date"] >= date("Y-m-d", strtotime("+1 month")))
-                                                <i class="ico--ui check active me-2"></i>
-                                                Scadenza :
-                                            @endif
-                                            {{$has_certificate["date"] != '' ? date("d/m/Y", strtotime($has_certificate["date"])) : ''}}
-                                        </span>
+                                        @if($has_certificate["date"] != '')
+                                            <b class=" tablesaw-cell-label">Scadenza certificato</b>
+                                            <span class="tablesaw-cell-content d-flex align-items-center">
+                                                @if($has_certificate["date"] < date("Y-m-d"))
+                                                    <i class="ico--ui check suspended me-2"></i>
+                                                    Scaduto :
+                                                @endif
+                                                @if($has_certificate["date"] >= date("Y-m-d") && $has_certificate["date"] < date("Y-m-d", strtotime("+1 month")))
+                                                    <i class="ico--ui check due me-2"></i>
+                                                    In scadenza :
+                                                @endif
+                                                @if($has_certificate["date"] >= date("Y-m-d", strtotime("+1 month")))
+                                                    <i class="ico--ui check active me-2"></i>
+                                                    Scadenza :
+                                                @endif
+                                                {{$has_certificate["date"] != '' ? date("d/m/Y", strtotime($has_certificate["date"])) : ''}}
+                                            </span>
+                                        @endif
                                     </td>
 
                                     <td>
@@ -421,6 +394,16 @@
 
                         </tbody>
                     </table>
+                    <div class="row">
+                        <div class="col-md-6">
+                            {{ $datas->links() }}
+                        </div>
+                        <div class="col-md-6 " style="text-align:right">
+                            <br><br><span class="tablesaw-cell-content">{{ $datas->total() }} utenti</span>
+                        </div>
+                    </div>
+
+
                     <!--
                     <div class="paginator d-flex justify-content-center">
                         <nav aria-label="Page navigation example">
@@ -777,9 +760,9 @@
                                                 </div>
                                                 <div class="col-6">
                                                     <label for="document_files" class="form-label">File</label>
-                                                    <input class="form-control" type="file" wire:model="documents" multiple>
-                                                    @foreach ($document_files as $d)
-                                                        <a href="{{ asset('storage/app/public/'.$d) }}" target="_blank" class="form-label">{{$d}}</a><br>
+                                                    <input class="form-control" type="file" wire:model="documents" multiple><br>
+                                                    @foreach ($document_files as $idx => $d)
+                                                        <a href="{{ asset('storage/app/public/'.$d) }}" target="_blank" class="form-label">{{$d}}</a> <a wire:click="removeDocument({{$idx}})" class="form-label">(elimina)</a><br>
                                                     @endforeach
                                                 </div>
 
@@ -928,6 +911,8 @@
                                     </div>
                                 @endif
 
+                                <span style="color:red">{!!$groupMsg!!}</span>
+
                                 @foreach($member_categories as $member_category)
                                     <div class="tessera--added d-flex align-items-center justify-content-between mt-4 mb-3">
                                         <div class="tessera--added_name d-flex align-items-start">
@@ -992,12 +977,15 @@
                                                 <div class="row ">
                                                     <div class="col-md-12">
                                                         <label for="course_course_id" class="form-label">Corso</label>
-                                                        <select id="course_course_id" class="form-select coursesClass @error('course_course_id') is-invalid @enderror" aria-label="Corso" wire:model="course_course_id">
-                                                            <option value="">--Seleziona--
-                                                            @foreach($courses as $course)
-                                                                <option value="{{$course["id"]}}">{{$course["name"]}}
-                                                            @endforeach
-                                                        </select>
+                                                        @livewire('courses', ['course_id' => $course_course_id])
+                                                        @if(false)
+                                                            <select id="course_course_id" class="form-select coursesClass @error('course_course_id') is-invalid @enderror" aria-label="Corso" wire:model="course_course_id">
+                                                                <option value="">--Seleziona--
+                                                                @foreach($courses as $course)
+                                                                    <option value="{{$course["id"]}}">{{$course["name"]}}
+                                                                @endforeach
+                                                            </select>
+                                                        @endif
                                                     </div>
                                                 </div>
                                                 <div class="row ">
@@ -1350,6 +1338,10 @@
             });
         });
 
+        Livewire.on('hide-search', () => {
+            pcsh2();
+        });
+
         function loadCombo()
         {
             $('.nationClass').select2({

+ 22 - 13
resources/views/livewire/records_in.blade.php

@@ -192,8 +192,9 @@
                             <tr>
                                 <th scope="col"></th>
                                 <th scope="col" wire:click.prevent="sortBy('date')" style="cursor:pointer">Data pagamento&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
-                                <th scope="col" wire:click.prevent="sortBy('total')" style="cursor:pointer">Importo&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
-                                <th scope="col" wire:click.prevent="sortBy('person')" style="cursor:pointer">Persona&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
+                                <th scope="col">Importo</th>
+                                <th scope="col" wire:click.prevent="sortBy('first_name')" style="cursor:pointer">Nome&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
+                                <th scope="col" wire:click.prevent="sortBy('last_name')" style="cursor:pointer">Cognome&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
                                 <th scope="col">Causale</th>
                                 <th scope="col" wire:click.prevent="sortBy('payment')" style="cursor:pointer">Pagamento&nbsp;&nbsp;&nbsp;<i class="fa fa-sort"></i></th>
 
@@ -201,15 +202,16 @@
                             </tr>
                         </thead>
                         <tbody id="checkall-target">
-                            @foreach($records as $record)
+                            @foreach($datas as $record)
                                 <tr>
                                     <td> <label><input class="table-check" type="checkbox" wire:model="multipleIds" value="{{$record->id}}"><span class="sr-only d-inline-block d-lg-none ms-2 mobile-row-selector"> Seleziona riga</span></label></td>
                                     <td>{{date("d/m/Y", strtotime($record->date))}}</td>
                                     <td><span class="tablesaw-cell-content primary">{{formatPrice($record->getTotal())}}</span></td>
                                     <td>
-                                        @if($record->member)
-                                            {{$record->member->first_name}} {{$record->member->last_name}}
-                                        @endif
+                                        {{$record->first_name}}
+                                    </td>
+                                    <td>
+                                        {{$record->last_name}}
                                     </td>
                                     <td>
                                         @foreach($record->rows as $row)
@@ -227,6 +229,7 @@
                             @endforeach
                         </tbody>
                     </table>
+                    {{ $datas->links() }}
 
                     <!--
                     <div class="paginator d-flex justify-content-center">
@@ -340,7 +343,9 @@
                                         <span class="title-form d-block w-100">Causale</span>
                                         <div class="col-md-12">
 
-                                            @livewire('causals', ['type' => 'IN', 'idx' => $idx, 'causal_id' => $rows[$idx]["causal_id"]])
+                                            <livewire:causals :type="$typeIN" :idx="$idx" :causal_id="$rows[$idx]['causal_id']" :wire:key="$idx" />
+
+
 
                                             @if(false)
                                             <select name="rows.{{$idx}}.causal_id" class="form-select causalClass @error('row.' . $idx . '.causal_id') is-invalid @enderror" aria-label="Seleziona una causale" wire:model="rows.{{$idx}}.causal_id">
@@ -491,7 +496,7 @@
 
                                         @if($this->member->isAdult())
                                             <li>
-                                                <span class="evidence_name">{{$this->member->first_name}}</span>
+                                                <span class="evidence_name">{{$this->member->last_name}} {{$this->member->first_name}}</span> ({{$this->member->fiscal_code}})
                                             </li>
                                             <li><span>Nato/a il {{$this->member->birth_date ? date("d/m/Y", strtotime($this->member->birth_date)) : ''}}</span></li>
                                         @else
@@ -540,8 +545,12 @@
                                     @if($currentReceip)
                                         @if($currentReceip->status == 99)
                                             <br><b style="float:right">Annullata</b>
+                                            <button class="btn--ui primary sendInvoice mt-5 d-flex ms-auto" wire:click.prevent="update(true)"><i class="ico--ui sendingBtn"></i>salva e rigenera ricevuta</button>
                                         @else
-                                            <button class="btn--ui  mt-5 d-flex ms-auto" wire:click.prevent="removeReceipt()"><i class="ico--ui sendingBtn"></i>annulla ricevuta</button>
+                                            <div class="mt-5">
+                                                <button class="btn--ui " wire:click="printReceipt()"><i class="ico--ui sendingBtn"></i>stampa ricevuta</button>
+                                                <button class="btn--ui " wire:click.prevent="removeReceipt()"><i class="ico--ui "></i>annulla ricevuta</button>
+                                            </div>
                                         @endif
                                     @else
                                         <button class="btn--ui primary sendInvoice mt-5 d-flex ms-auto" wire:click.prevent="update(true)"><i class="ico--ui sendingBtn"></i>salva e genera ricevuta</button>
@@ -646,7 +655,7 @@
                     }
                 });
                 $('.memberClass').select2({
-                    tags: true
+                    tags: false
                 });
                 $('.paymentClass').select2({
                     matcher: function(params, data) {
@@ -658,7 +667,7 @@
         window.livewire.on('refresh', () => {
             // $('.causalClass').select2();
             $('.memberClass').select2({
-                tags: true
+                tags: false
             });
             $('.paymentClass').select2({
                 matcher: function(params, data) {
@@ -684,7 +693,7 @@
             });
 
             $('.memberClass').select2({
-                tags: true
+                tags: false
             });
             $('.memberClass').on('change', function (e) {
                 var data = $('.memberClass').select2("val");
@@ -728,7 +737,7 @@
         window.livewire.on('reloadMembers', () => {
             $('.memberClass').select2("destroy");
             $('.memberClass').select2({
-                tags: true
+                tags: false
             });
         });
 

+ 193 - 185
resources/views/livewire/records_in_out.blade.php

@@ -15,125 +15,193 @@
 
             </header>
 
-            <section id="subheader" class="d-flex">
-                <form action="" class="d-flex">
-                   <select class="form-select form-select-lg me-1"  wire:model="month" style="width:150px !important;">
-                        <option value="1" {{$month == 1 ? 'selected' : ''}}>Gennaio</option>
-                        <option value="2" {{$month == 2 ? 'selected' : ''}}>Febbraio</option>
-                        <option value="3" {{$month == 3 ? 'selected' : ''}}>Marzo</option>
-                        <option value="4" {{$month == 4 ? 'selected' : ''}}>Aprile</option>
-                        <option value="5" {{$month == 5 ? 'selected' : ''}}>Maggio</option>
-                        <option value="6" {{$month == 6 ? 'selected' : ''}}>Giugno</option>
-                        <option value="7" {{$month == 7 ? 'selected' : ''}}>Luglio</option>
-                        <option value="8" {{$month == 8 ? 'selected' : ''}}>Agosto</option>
-                        <option value="9" {{$month == 9 ? 'selected' : ''}}>Settembre</option>
-                        <option value="10" {{$month == 10 ? 'selected' : ''}}>Ottobre</option>
-                        <option value="11" {{$month == 11 ? 'selected' : ''}}>Novembre</option>
-                        <option value="12" {{$month == 12 ? 'selected' : ''}}>Dicembre</option>
+            <section id="subheader" class="d-flex align-items-center ">
+                <form action="" class=" d-flex align-items-center">
+
+                   <select class="form-select form-select-lg me-1 " id="month"  style="width:150px !important;">
+                        <option value="1">Gennaio</option>
+                        <option value="2">Febbraio</option>
+                        <option value="3">Marzo</option>
+                        <option value="4">Aprile</option>
+                        <option value="5">Maggio</option>
+                        <option value="6">Giugno</option>
+                        <option value="7">Luglio</option>
+                        <option value="8">Agosto</option>
+                        <option value="9">Settembre</option>
+                        <option value="10">Ottobre</option>
+                        <option value="11">Novembre</option>
+                        <option value="12">Dicembre</option>
                     </select>
-                </form>
-                <form action="" class="d-flex">
-                    <select class="form-select "  wire:model="year" style="width:100px !important;">
+
+                    <select class="form-select " style="width:100px !important;" id="year">
                         @for($y=date("Y"); $y>date("Y") - 2; $y--)
                             <option value="{{$y}}">{{$y}}</option>
                         @endfor
                     </select>
+
                 </form>
+                @if(sizeof($columns) < 6)
+                    <button class="btn--ui show" style="margin-left:5px;">aggiungi</button>
+                @endif
 
-                @if($total_in > 0 || $total_out > 0)
-                    <h4  style="width:100%;text-align:right">Totale mese entrate/uscite : <span class="tablesaw-cell-content primary" style="color:{{$total_in - $total_out > 0 ? 'green' : 'red'}}">{{formatPrice($total_in - $total_out)}}</span></h4>
+                <button class="btn--ui reset" wire:click="clear()" style="margin-left:5px;">reset</button>
+                @if($showData)
+                    <button class="btn--ui reset" wire:click="export()" style="margin-left:5px;">esporta</button>
+                    <button class="btn--ui reset" wire:click="exportYear()" style="margin-left:5px;">esporta anno selezionato</button>
                 @endif
 
             </section>
 
 
-            <section id="resume-table">
-
+                <section id="resume-table">
 
-                <div class="compare--chart_wrapper d-none"></div>
+                    <div class="compare--chart_wrapper d-none"></div>
 
-                <div class="row ">
-                    <div class="col-md-6">
+                    <div class="row ">
+                        <div class="col-md-12">
 
-                        <h1>Entrate</h1>
+                            <h1>Entrate</h1>
 
-                        <table class="table tablesaw tablesaw-stack" data-tablesaw="" id="tablesaw-350">
-                            <thead>
-                                <tr>
-                                    <th scope="col">Data</th>
-                                    <th scope="col">Cliente</th>
-                                    <th scope="col">Causale</th>
-                                    <th scope="col"  style="text-align:right;">Importo</th>
-                                </tr>
-                            </thead>
-                            <tbody id="checkall-target">
-                                @foreach($records_in as $record)
+                            <table class="table tablesaw tablesaw-stack collaptableIN" >
+                                <thead>
+                                    <tr>
+                                        <th scope="col" style="width:20%;text-align:left"></th>
+                                        @foreach($columns as $idx => $column)
+                                            <th scope="col cellBorder" style="width:13%;text-align:center">{{$this->getMonth($column)}} <br><a href="#" wire:click="remove({{$idx}})"><i class="fa fa-trash" aria-hidden="true" style="color:red"></i></a></th>
+                                        @endforeach
+                                        @for($j=sizeof($columns);$j<6;$j++)
+                                            <th scope="col cellBorder" style="width:13%;text-align:center">&nbsp;</th>
+                                        @endfor
+                                    </tr>
+                                </thead>
+                                <tbody id="checkall-target">
+
+                                    @foreach($rows_in as $in)
+                                        <tr data-id="{{$in["id"]}}" data-parent="{{$in["parent_id"]}}">
+                                            <td>{!!str_repeat("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", $in["level"])!!}{{$in["name"]}}</td>
+                                            @foreach($columns as $column)
+                                                <td class="cellBorder" style="text-align:center">
+                                                    @if(isset($records_in[$column][$in["id"]]))
+                                                        <span class="tablesaw-cell-content {{$in["level"] == 0 ? 'primary' : ''}}">
+                                                        {{formatPrice($records_in[$column][$in["id"]])}}
+                                                        </span>
+                                                    @else
+                                                        &nbsp;
+                                                    @endif
+                                                </td>
+                                            @endforeach
+                                            @for($j=sizeof($columns);$j<6;$j++)
+                                                <td class="cellBorder">&nbsp;</th>
+                                            @endfor
+                                        </tr>
+                                    @endforeach
                                     <tr>
-                                        <td>{{date("d/m/Y", strtotime($record->date))}}</td>
-                                        <td>
-                                            @if($record->member)
-                                                {{$record->member->first_name}} {{$record->member->last_name}}
-                                            @endif
-                                        </td>
-                                        <td><a href="/in?id={{$record->record_id}}">{{$this->getCausal($record->causal_id)}}</a></td>
-                                        <td style="text-align:right;"><span class="tablesaw-cell-content primary">{{formatPrice($record->amount)}}</span></td>
+                                        <td><b>Totale entrate mensili</b></td>
+                                        @foreach($columns as $column)
+                                            <td class="cellBorder" style="text-align:center">
+                                                @php
+                                                $total = 0;
+                                                @endphp
+                                                @foreach($rows_in as $in)
+                                                    @if(isset($records_in[$column][$in["id"]]) && $in["level"] == 0)
+                                                        @php
+                                                        $total += $records_in[$column][$in["id"]];
+                                                        @endphp
+                                                    @endif
+                                                @endforeach
+                                                <span class="tablesaw-cell-content primary" style="color:green"><b>{{formatPrice($total)}}</b></span>
+                                            </td>
+                                        @endforeach
+                                        @for($j=sizeof($columns);$j<6;$j++)
+                                            <td class="cellBorder">&nbsp;</th>
+                                        @endfor
                                     </tr>
-                                @endforeach
-                                <tr>
-                                    <td></td>
-                                    <td></td>
-                                    <td><b>Totale</b></td>
-                                    <td style="text-align:right;"><span class="tablesaw-cell-content primary" style="color:green"><b>{{formatPrice($total_in)}}</b></span></td>
-                                </tr>
-                            </tbody>
-                            <tfoot>
-
-                            </tfoot>
-                        </table>
+
+                                </tbody>
+                                <tfoot>
+
+                                </tfoot>
+                            </table>
+                        </div>
                     </div>
+                    <div class="row ">
+                        <div class="col-md-12">
+
+                            <h1>Uscite</h1>
+
+                            <table class="table tablesaw tablesaw-stack collaptableOUT">
+                                <thead>
+                                    <tr>
+                                        <th scope="col" style="width:20%;text-align:left"></th>
+                                        @foreach($columns as $idx => $column)
+                                            <th scope="col cellBorder" style="width:13%;text-align:center">{{$this->getMonth($column)}} <br><a href="#" wire:click="remove({{$idx}})"><i class="fa fa-trash" aria-hidden="true" style="color:red"></i></a></th>
+                                        @endforeach
+                                        @for($j=sizeof($columns);$j<6;$j++)
+                                            <th scope="col cellBorder" style="width:13%;text-align:center">&nbsp;</th>
+                                        @endfor
+                                    </tr>
+                                </thead>
+                                <tbody id="checkall-target">
+
+                                    @foreach($rows_out as $out)
+                                        <tr data-id="{{$out["id"] + 1000}}" data-parent="{{$out["parent_id"] != null ? ($out["parent_id"] + 1000) : 0}}">
+                                            <td>{!!str_repeat("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;", $out["level"])!!}{{$out["name"]}}</td>
+                                            @foreach($columns as $column)
+                                                <td class="cellBorder" style="text-align:center">
+                                                    @if(isset($records_out[$column][$out["id"]]))
+                                                        <span class="tablesaw-cell-content {{$out["level"] == 0 ? 'primary' : ''}}">
+                                                        {{formatPrice($records_out[$column][$out["id"]])}}
+                                                        </span>
+                                                    @else
+                                                        &nbsp;
+                                                    @endif
+                                                </td>
+                                            @endforeach
+                                            @for($j=sizeof($columns);$j<6;$j++)
+                                                <td class="cellBorder">&nbsp;</th>
+                                            @endfor
+                                        </tr>
+                                    @endforeach
 
-                    <div class="col-md-6">
-
-                        <h1>Uscite</h1>
-
-                        <table class="table tablesaw tablesaw-stack" data-tablesaw="" id="tablesaw-350x">
-                            <thead>
-                                <tr>
-                                    <th scope="col">Data</th>
-                                    <th scope="col">Fornitore</th>
-                                    <th scope="col">Causale</th>
-                                    <th scope="col" style="text-align:right;">Importo</th>
-                                </tr>
-                            </thead>
-                            <tbody id="checkall-target">
-                                @foreach($records_out as $record)
                                     <tr>
-                                        <td>{{date("d/m/Y", strtotime($record->date))}}</td>
-                                        <td>
-                                            @if($record->supplier)
-                                                {{$record->supplier->name}}
-                                            @endif
-                                        </td>
-                                        <td>{{$this->getCausal($record->causal_id)}}</td>
-                                        <td style="text-align:right;"><span class="tablesaw-cell-content primary">{{formatPrice($record->amount)}}</span></td>
+                                        <td><b>Totale uscite mensili</b></td>
+                                        @foreach($columns as $column)
+                                            <td class="cellBorder" style="text-align:center">
+                                                @php
+                                                $total = 0;
+                                                @endphp
+                                                @foreach($rows_out as $out)
+                                                    @if(isset($records_out[$column][$out["id"]]) && $out["level"] == 0)
+                                                        @php
+                                                        $total += $records_out[$column][$out["id"]];
+                                                        @endphp
+                                                    @endif
+                                                @endforeach
+                                                <span class="tablesaw-cell-content primary" style="color:red"><b>{{formatPrice($total)}}</b></span>
+                                            </td>
+                                        @endforeach
+                                        @for($j=sizeof($columns);$j<6;$j++)
+                                            <td class="cellBorder">&nbsp;</th>
+                                        @endfor
                                     </tr>
-                                @endforeach
-                                <tr>
-                                    <td></td>
-                                    <td></td>
-                                    <td><b>Totale</b></td>
-                                    <td style="text-align:right;"><span class="tablesaw-cell-content primary" style="color:red"><b>{{formatPrice($total_out)}}</b></span></td>
-                                </tr>
-                            </tbody>
-                        </table>
+
+                                </tbody>
+                                <tfoot>
+
+                                </tfoot>
+                            </table>
+                        </div>
+
                     </div>
-                </div>
-            </section>
+                </section>
+
+
 
         </div>
     </div>
 </div>
 
+
 @push('scripts')
     <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
     <style>
@@ -153,114 +221,54 @@
         .select2 {
             width:100% !important;
         }
+        .i{
+            font-size:16px;
+            font-weight:bold;
+        }
+        .cellBorder
+        {
+            border-left: 1px solid grey;
+        }
     </style>
     <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
     <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
+    <script src="/assets/js/aCollapTable.js"></script>
 @endpush
 
 @push('scripts')
     <script>
-        function matchStart(params, data) {
-            params.term = params.term || '';
-            if (data.text.toUpperCase().indexOf(params.term.toUpperCase()) == 0) {
-                return data;
-            }
-            return false;
-        }
-
-        window.livewire.on('refresh', () => {
-            $('.causalClass').select2();
-            $('.memberClass').select2({
-                matcher: function(params, data) {
-                    return matchStart(params, data);
-                }
-            });
-            $('.paymentClass').select2({
-                matcher: function(params, data) {
-                    return matchStart(params, data);
-                }
-            });
-        });
-        Livewire.on('load-select', () => {
-            $('.causalClass').select2();
-            $('.causalClass').on('change', function (e) {
-                var data = $('.causalClass').select2("val");
-                @this.set('causal_id', data);
-            });
-            $('.memberClass').select2({
-                matcher: function(params, data) {
-                    return matchStart(params, data);
-                }
-            });
-            $('.memberClass').on('change', function (e) {
-                var data = $('.memberClass').select2("val");
-                @this.set('member_id', data);
-            });
-            $('.paymentClass').select2({
-                matcher: function(params, data) {
-                    return matchStart(params, data);
-                }
-            });
-            $('.paymentClass').on('change', function (e) {
-                var data = $('.paymentClass').select2("val");
-                @this.set('payment_method_id', data);
-            });
-
-            $('.filterMember').select2();
-            $('.filterMember').on('change', function (e) {
-                var data = $('.filterMember').select2("val");
-                @this.set('filterMember', data);
-            });
-            $('.filterPaymentMethod').select2();
-            $('.filterPaymentMethod').on('change', function (e) {
-                var data = $('.filterPaymentMethod').select2("val");
-                @this.set('filterPaymentMethod', data);
-            });
-            $('.filterCausals').select2();
-            $('.filterCausals').on('change', function (e) {
-                var data = $('.filterCausals').select2("val");
-                @this.set('filterCausals', data);
-            });
 
+        Livewire.on('load-table', () => {
+            load();
         });
 
-        Livewire.on('hide-search', () => {
-            pcsh2();
-        });
 
-        window.livewire.on('saved', () => {
-            $('#userModal').modal('hide');
-        });
-        window.livewire.on('reloadMembers', () => {
-            $('.memberClass').select2("destroy");
-            $('.memberClass').select2({
-                matcher: function(params, data) {
-                    return matchStart(params, data);
-                }
+        function load()
+        {
+            $(document).ready(function(){
+                $('.collaptableIN').aCollapTable({
+                    startCollapsed: true,
+                    addColumn: false,
+                    plusButton: '<span class="i"> + </span>',
+                    minusButton: '<span class="i"> - </span>'
+                });
+                $('.collaptableOUT').aCollapTable({
+                    startCollapsed: true,
+                    addColumn: false,
+                    plusButton: '<span class="i"> + </span>',
+                    minusButton: '<span class="i"> - </span>'
+                });
+                $(".act-button-collapse-all").trigger('click');
             });
-        });
+        }
 
-        $('.filterMember').select2();
-        $('.filterMember').on('change', function (e) {
-            var data = $('.filterMember').select2("val");
-            @this.set('filterMember', data);
-        });
-        $('.filterPaymentMethod').select2();
-        $('.filterPaymentMethod').on('change', function (e) {
-            var data = $('.filterPaymentMethod').select2("val");
-            @this.set('filterPaymentMethod', data);
-        });
-        $('.filterCausals').select2();
-        $('.filterCausals').on('change', function (e) {
-            var data = $('.filterCausals').select2("val");
-            @this.set('filterCausals', data);
-        });
+        load();
 
-        function onlyNumberAmount(input) {
-            let v = input.value.replace(/\D+/g, '');
-            if (v.length > 14) v = v.slice(0, 14);
-            input.value = "€ " + v.replace(/(\d)(\d\d)$/, "$1,$2").replace(/(^\d{1,3}|\d{3})(?=(?:\d{3})+(?:,|$))/g, '$1.');
-        }
+        $(document).on("click", ".show", function () {
+            var m = $('#month').val();
+            var y = $('#year').val();
+            @this.show(m, y);
+        });
 
     </script>
 

+ 281 - 0
resources/views/livewire/records_in_out_old.blade.php

@@ -0,0 +1,281 @@
+<div class="col">
+    <div class="row h-100">
+
+
+        <div class="col card--ui" id="card--dashboard">
+
+
+            <header id="title--section" class="d-flex align-items-center justify-content-between">
+                <div class="title--section_name d-flex align-items-center justify-content-between">
+                    <i class="ico--ui title_section utenti me-2"></i>
+                    <h2 class="primary">Entrate/Uscite gestionale</h2>
+                </div>
+
+
+
+            </header>
+
+            <section id="subheader" class="d-flex">
+                <form action="" class="d-flex">
+                   <select class="form-select form-select-lg me-1 months"  wire:model="month" style="width:150px !important;">
+                        <option value="1" {{$month == 1 ? 'selected' : ''}}>Gennaio</option>
+                        <option value="2" {{$month == 2 ? 'selected' : ''}}>Febbraio</option>
+                        <option value="3" {{$month == 3 ? 'selected' : ''}}>Marzo</option>
+                        <option value="4" {{$month == 4 ? 'selected' : ''}}>Aprile</option>
+                        <option value="5" {{$month == 5 ? 'selected' : ''}}>Maggio</option>
+                        <option value="6" {{$month == 6 ? 'selected' : ''}}>Giugno</option>
+                        <option value="7" {{$month == 7 ? 'selected' : ''}}>Luglio</option>
+                        <option value="8" {{$month == 8 ? 'selected' : ''}}>Agosto</option>
+                        <option value="9" {{$month == 9 ? 'selected' : ''}}>Settembre</option>
+                        <option value="10" {{$month == 10 ? 'selected' : ''}}>Ottobre</option>
+                        <option value="11" {{$month == 11 ? 'selected' : ''}}>Novembre</option>
+                        <option value="12" {{$month == 12 ? 'selected' : ''}}>Dicembre</option>
+                    </select>
+                </form>
+                <form action="" class="d-flex">
+                    <select class="form-select "  wire:model="year" style="width:100px !important;">
+                        @for($y=date("Y"); $y>date("Y") - 2; $y--)
+                            <option value="{{$y}}">{{$y}}</option>
+                        @endfor
+                    </select>
+                </form>
+
+                @if($total_in > 0 || $total_out > 0)
+                    <h4  style="width:100%;text-align:right">Totale mese entrate/uscite : <span class="tablesaw-cell-content primary" style="color:{{$total_in - $total_out > 0 ? 'green' : 'red'}}">{{formatPrice($total_in - $total_out)}}</span></h4>
+                @endif
+
+            </section>
+
+
+            <section id="resume-table">
+
+
+                <div class="compare--chart_wrapper d-none"></div>
+
+                <div class="row ">
+                    <div class="col-md-6">
+
+                        <h1>Entrate</h1>
+
+                        <table class="table tablesaw tablesaw-stack" data-tablesaw="" id="tablesaw-350">
+                            <thead>
+                                <tr>
+                                    <th scope="col">Data</th>
+                                    <th scope="col">Cliente</th>
+                                    <th scope="col">Causale</th>
+                                    <th scope="col"  style="text-align:right;">Importo</th>
+                                </tr>
+                            </thead>
+                            <tbody id="checkall-target">
+                                @foreach($records_in as $record)
+                                    <tr>
+                                        <td>{{date("d/m/Y", strtotime($record->date))}}</td>
+                                        <td>
+                                            @if($record->member)
+                                                {{$record->member->first_name}} {{$record->member->last_name}}
+                                            @endif
+                                        </td>
+                                        <td><a href="/in?id={{$record->record_id}}">{{$this->getCausal($record->causal_id)}}</a></td>
+                                        <td style="text-align:right;"><span class="tablesaw-cell-content primary">{{formatPrice($record->amount)}}</span></td>
+                                    </tr>
+                                @endforeach
+                                <tr>
+                                    <td></td>
+                                    <td></td>
+                                    <td><b>Totale</b></td>
+                                    <td style="text-align:right;"><span class="tablesaw-cell-content primary" style="color:green"><b>{{formatPrice($total_in)}}</b></span></td>
+                                </tr>
+                            </tbody>
+                            <tfoot>
+
+                            </tfoot>
+                        </table>
+                    </div>
+
+                    <div class="col-md-6">
+
+                        <h1>Uscite</h1>
+
+                        <table class="table tablesaw tablesaw-stack" data-tablesaw="" id="tablesaw-350x">
+                            <thead>
+                                <tr>
+                                    <th scope="col">Data</th>
+                                    <th scope="col">Fornitore</th>
+                                    <th scope="col">Causale</th>
+                                    <th scope="col" style="text-align:right;">Importo</th>
+                                </tr>
+                            </thead>
+                            <tbody id="checkall-target">
+                                @foreach($records_out as $record)
+                                    <tr>
+                                        <td>{{date("d/m/Y", strtotime($record->date))}}</td>
+                                        <td>
+                                            @if($record->supplier)
+                                                {{$record->supplier->name}}
+                                            @endif
+                                        </td>
+                                        <td>{{$this->getCausal($record->causal_id)}}</td>
+                                        <td style="text-align:right;"><span class="tablesaw-cell-content primary">{{formatPrice($record->amount)}}</span></td>
+                                    </tr>
+                                @endforeach
+                                <tr>
+                                    <td></td>
+                                    <td></td>
+                                    <td><b>Totale</b></td>
+                                    <td style="text-align:right;"><span class="tablesaw-cell-content primary" style="color:red"><b>{{formatPrice($total_out)}}</b></span></td>
+                                </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </section>
+
+        </div>
+    </div>
+</div>
+
+@push('scripts')
+    <link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
+    <style>
+        .select2-container--default .select2-selection--single{
+            background-color: #E9F0F5;
+            border: 0.0625rem solid #DFE5EB;
+            font-size: 0.75rem;
+        }
+        .select2-selection
+        {
+            height: 38px !important;
+        }
+        .select2-selection__rendered
+        {
+            padding-top:3px;
+        }
+        .select2 {
+            width:100% !important;
+        }
+    </style>
+    <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
+    <script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
+@endpush
+
+@push('scripts')
+    <script>
+
+        $(".months").select2({
+            closeOnSelect : false,
+            placeholder : "Placeholder",
+            allowHtml: true,
+            allowClear: true,
+            tags: true // создает новые опции на лету
+		});
+        /*
+        function matchStart(params, data) {
+            params.term = params.term || '';
+            if (data.text.toUpperCase().indexOf(params.term.toUpperCase()) == 0) {
+                return data;
+            }
+            return false;
+        }
+
+        window.livewire.on('refresh', () => {
+            $('.causalClass').select2();
+            $('.memberClass').select2({
+                matcher: function(params, data) {
+                    return matchStart(params, data);
+                }
+            });
+            $('.paymentClass').select2({
+                matcher: function(params, data) {
+                    return matchStart(params, data);
+                }
+            });
+        });
+        Livewire.on('load-select', () => {
+
+
+
+
+            $('.causalClass').select2();
+            $('.causalClass').on('change', function (e) {
+                var data = $('.causalClass').select2("val");
+                @this.set('causal_id', data);
+            });
+            $('.memberClass').select2({
+                matcher: function(params, data) {
+                    return matchStart(params, data);
+                }
+            });
+            $('.memberClass').on('change', function (e) {
+                var data = $('.memberClass').select2("val");
+                @this.set('member_id', data);
+            });
+            $('.paymentClass').select2({
+                matcher: function(params, data) {
+                    return matchStart(params, data);
+                }
+            });
+            $('.paymentClass').on('change', function (e) {
+                var data = $('.paymentClass').select2("val");
+                @this.set('payment_method_id', data);
+            });
+
+            $('.filterMember').select2();
+            $('.filterMember').on('change', function (e) {
+                var data = $('.filterMember').select2("val");
+                @this.set('filterMember', data);
+            });
+            $('.filterPaymentMethod').select2();
+            $('.filterPaymentMethod').on('change', function (e) {
+                var data = $('.filterPaymentMethod').select2("val");
+                @this.set('filterPaymentMethod', data);
+            });
+            $('.filterCausals').select2();
+            $('.filterCausals').on('change', function (e) {
+                var data = $('.filterCausals').select2("val");
+                @this.set('filterCausals', data);
+            });
+
+        });
+
+        Livewire.on('hide-search', () => {
+            pcsh2();
+        });
+
+        window.livewire.on('saved', () => {
+            $('#userModal').modal('hide');
+        });
+        window.livewire.on('reloadMembers', () => {
+            $('.memberClass').select2("destroy");
+            $('.memberClass').select2({
+                matcher: function(params, data) {
+                    return matchStart(params, data);
+                }
+            });
+        });
+
+        $('.filterMember').select2();
+        $('.filterMember').on('change', function (e) {
+            var data = $('.filterMember').select2("val");
+            @this.set('filterMember', data);
+        });
+        $('.filterPaymentMethod').select2();
+        $('.filterPaymentMethod').on('change', function (e) {
+            var data = $('.filterPaymentMethod').select2("val");
+            @this.set('filterPaymentMethod', data);
+        });
+        $('.filterCausals').select2();
+        $('.filterCausals').on('change', function (e) {
+            var data = $('.filterCausals').select2("val");
+            @this.set('filterCausals', data);
+        });
+
+        function onlyNumberAmount(input) {
+            let v = input.value.replace(/\D+/g, '');
+            if (v.length > 14) v = v.slice(0, 14);
+            input.value = "€ " + v.replace(/(\d)(\d\d)$/, "$1,$2").replace(/(^\d{1,3}|\d{3})(?=(?:\d{3})+(?:,|$))/g, '$1.');
+        }
+        */
+
+    </script>
+
+@endpush

+ 1 - 1
resources/views/livewire/records_out.blade.php

@@ -309,7 +309,7 @@
                                         <span class="title-form d-block w-100">Causale</span>
                                         <div class="col-md-12">
 
-                                            @livewire('causals', ['type' => 'OUT', 'idx' => $idx, 'causal_id' => $rows[$idx]["causal_id"]])
+                                            <livewire:causals :type="$typeOUT" :idx="$idx" :causal_id="$rows[$idx]['causal_id']" :wire:key="$idx" />
 
                                             @if(false)
                                                 <select name="rows.{{$idx}}.causal_id" class="form-select causalClass @error('row.' . $idx . '.causal_id') is-invalid @enderror" aria-label="Seleziona una causale" wire:model="rows.{{$idx}}.causal_id">

+ 57 - 0
resources/views/receipt.blade.php

@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title></title>
+  <style>
+    body {
+        font-family: Helvetica, Arial, sans-serif;
+        font-size:14px;
+    }
+    footer {
+        position: fixed;
+        bottom: -20px;
+        left: 0px;
+        right: 0px;
+        height: 50px;
+
+    }
+    </style>
+</head>
+<body>
+    <img src="{{public_path() . env('LOGO')}}" width="200">
+    <br><br><br>
+    <b>Associazione</b>: {{env('RAGIONE_SOCIALE', '')}}<br><br>
+    <b>Via</b>: {{env('INDIRIZZO', '')}} {{env('LOCALITA', '')}} ({{env('PROVINCIA', '')}})<br><br>
+    <b>C.F.</b>: {{env('CODICE_FISCALE', '')}}<br><br>
+    <b>P.IVA</b>: {{env('PARTITA_IVA', '')}}<br><br>
+    <hr><br>
+    <b>Intestata a</b><br><br>
+    @if(!$receipt->member->isAdult())
+        <b>Padre</b>: {{$receipt->member->father_name}}<br><br>
+        <b>Madre</b>: {{$receipt->member->mother_name}}<br><br>
+    @endif
+    <b>Cognome</b>: {{$receipt->member->last_name}}<br><br>
+    <b>Nome</b>: {{$receipt->member->first_name}}<br><br>
+    <b>Nata a</b>: {{@$receipt->member->birth_city->name}} ({{@$receipt->member->birth_province->name}}) il {{$receipt->member->birth_date ? date("d/m/Y", strtotime($receipt->member->birth_date)) : ""}}<br><br>
+    <b>Residente in</b>: {{$receipt->member->address}} {{@$receipt->member->city->name}} ({{@$receipt->member->province->name}})<br><br>
+    <b>Codice Fiscale</b>: {{$receipt->member->fiscal_code}}<br><br>
+    <hr><br>
+    <b>RICEVUTA DI PAGAMENTO N. {{$receipt->number . "/" . $receipt->year}}</b><br><br>
+    @php
+    $total = 0;
+    @endphp
+    @foreach($receipt->rows as $row)
+        <b>Descrizione</b>: {{@$row->causal->getTree()}}<br><br>
+        <b>Importo</b>: {{formatPrice($row->amount)}}<br><br>
+        @php
+        $total += $row->amount;
+        @endphp
+    @endforeach
+    <br><br>
+    <b>Totale</b>: {{formatPrice($total)}}
+    <footer>
+        <small>{{env('LOCALITA', '')}} ({{env('PROVINCIA', '')}}) li {{date("d/m/Y", strtotime($receipt->date))}}</small>
+    </footer>
+
+</body>
+</html>