Просмотр исходного кода

Cassa e carrello: checkout, binding dispositivo e import saltacoda.

Rimosso il dump sulla cassa occupata; il carrello resta l'ordine in sessione.

Co-authored-by: Cursor <cursoragent@cursor.com>
marcofalabretti 2 недель назад
Родитель
Сommit
fdef65ba82

+ 30
- 8
app/DataTables/OrdineDataTableEditor.php Просмотреть файл

3
 namespace App\DataTables;
3
 namespace App\DataTables;
4
 
4
 
5
 use App\Models\Ordine;
5
 use App\Models\Ordine;
6
+use App\Models\Prenotazione;
6
 use Illuminate\Database\Eloquent\Model;
7
 use Illuminate\Database\Eloquent\Model;
7
-use Illuminate\Validation\Rule;
8
 use Yajra\DataTables\DataTablesEditor;
8
 use Yajra\DataTables\DataTablesEditor;
9
-use Illuminate\Http\Request;
10
-use Illuminate\Validation\ValidationException;
11
-use Storage;
12
-use Illuminate\Support\Str;
9
+use App\Services\Attivita\AttivitaService;
10
+use Illuminate\Support\Facades\Session;
13
 
11
 
14
 class OrdineDataTableEditor extends DataTablesEditor
12
 class OrdineDataTableEditor extends DataTablesEditor
15
 {
13
 {
91
 
89
 
92
   public function creating(Model $model, array $data): array
90
   public function creating(Model $model, array $data): array
93
   {
91
   {
94
-    // $model->roles()->sync([$data['ruolo_id']]);
92
+    $data['attivita_id'] = Session::get('attivita_attuale');
93
+    AttivitaService::garantisciAttivita($data['attivita_id']);
94
+    $this->garantisciPrenotazioneDiQuestaAttivita($data['prenotazione_id'] ?? null, $data['attivita_id']);
95
+
95
     return $data;
96
     return $data;
96
   }
97
   }
97
 
98
 
98
   public function updating(Model $model, array $data): array
99
   public function updating(Model $model, array $data): array
99
   {
100
   {
100
-    // dd($data['ruolo']);
101
-    // $model->roles()->sync([$data['ruolo_id']]);
101
+    AttivitaService::garantisciAttivita($model->attivita_id);
102
+    unset($data['attivita_id']);
103
+    $this->garantisciPrenotazioneDiQuestaAttivita($data['prenotazione_id'] ?? $model->prenotazione_id, $model->attivita_id);
104
+
102
     return $data;
105
     return $data;
103
   }
106
   }
107
+
108
+  public function deleting(Model $model, array $data): array
109
+  {
110
+    AttivitaService::garantisciAttivita($model->attivita_id);
111
+
112
+    return $data;
113
+  }
114
+
115
+  private function garantisciPrenotazioneDiQuestaAttivita($prenotazioneId, $attivitaId): void
116
+  {
117
+    if (! $prenotazioneId) {
118
+      return;
119
+    }
120
+
121
+    $prenotazione = Prenotazione::with('evento')->find($prenotazioneId);
122
+    if (! $prenotazione || (int) $prenotazione->evento?->attivita_id !== (int) $attivitaId) {
123
+      abort(404);
124
+    }
125
+  }
104
   public function messages(): array
126
   public function messages(): array
105
   {
127
   {
106
     return $this->messages;
128
     return $this->messages;

+ 12
- 12
app/DataTables/PiattoDataTable.php Просмотреть файл

80
      */
80
      */
81
     public function query(Piatto $model): QueryBuilder
81
     public function query(Piatto $model): QueryBuilder
82
     {
82
     {
83
-        if($this->attivita_id !== null){
84
-            $model = $model->newQuery()->where('attivita_id', $this->attivita_id);
85
-            
86
-            if (isset($this->cucina_id)) {
87
-                return $model->where('cucina_id', $this->cucina_id)
88
-                    ->with('cucina', 'elencoAllergeni');
89
-            }
83
+        $attivitaId = (int) $this->attivita_id;
84
+        if ($attivitaId <= 0) {
85
+            return $model->newQuery()->whereRaw('1 = 0');
86
+        }
90
 
87
 
91
-            return $model->with('cucina', 'elencoAllergeni');
88
+        $model = $model->newQuery()->where('attivita_id', $attivitaId);
92
 
89
 
93
-        }else{
94
-            return $model->newQuery()->whereRaw('1 = 0');
90
+        if (isset($this->cucina_id)) {
91
+            return $model->where('cucina_id', $this->cucina_id)
92
+                ->with('cucina', 'elencoAllergeni');
95
         }
93
         }
94
+
95
+        return $model->with('cucina', 'elencoAllergeni');
96
     }
96
     }
97
 
97
 
98
     /**
98
     /**
145
                 Editor::make()
145
                 Editor::make()
146
                     ->ajax(route('piatto.store'))
146
                     ->ajax(route('piatto.store'))
147
                     ->fields([
147
                     ->fields([
148
-                        Fields\Hidden::make('attivita_id')->label('Attività')->default($this->attivita_id),
148
+                        Fields\Hidden::make('attivita_id')->label('Attività')->default((int) $this->attivita_id),
149
                         Fields\Text::make('nome')->label('Nome'),
149
                         Fields\Text::make('nome')->label('Nome'),
150
                         Fields\Text::make('descrizione')->label('Descrizione'),
150
                         Fields\Text::make('descrizione')->label('Descrizione'),
151
                         Fields\Select2::make('cucina_id')->label('cucina')
151
                         Fields\Select2::make('cucina_id')->label('cucina')
152
-                        ->options(Cucina::where('is_attiva', true)->where('attivita_id', $this->attivita_id)->pluck('id', 'nome'))
152
+                        ->options(Cucina::where('is_attiva', true)->where('attivita_id', (int) $this->attivita_id)->pluck('id', 'nome'))
153
                         ->default(isset($this->cucina_id) ? $this->cucina_id : ''),
153
                         ->default(isset($this->cucina_id) ? $this->cucina_id : ''),
154
                         Fields\Text::make('prezzo')->label('Prezzo (€)'),
154
                         Fields\Text::make('prezzo')->label('Prezzo (€)'),
155
                         // Fields\Image::make('immagine')->label('Immagine'),
155
                         // Fields\Image::make('immagine')->label('Immagine'),

+ 28
- 7
app/DataTables/PiattoDataTableEditor.php Просмотреть файл

2
 
2
 
3
 namespace App\DataTables;
3
 namespace App\DataTables;
4
 
4
 
5
+use App\Models\Cucina;
5
 use App\Models\Piatto;
6
 use App\Models\Piatto;
6
 use App\Models\PiattoHasAllergene;
7
 use App\Models\PiattoHasAllergene;
8
+use App\Services\Attivita\AttivitaService;
7
 use Illuminate\Database\Eloquent\Model;
9
 use Illuminate\Database\Eloquent\Model;
8
-use Illuminate\Validation\Rule;
9
 use Yajra\DataTables\DataTablesEditor;
10
 use Yajra\DataTables\DataTablesEditor;
10
-use Illuminate\Http\Request;
11
-use Illuminate\Validation\ValidationException;
12
-use Storage;
13
-use Illuminate\Support\Str;
11
+use Illuminate\Support\Facades\Session;
14
 
12
 
15
 class PiattoDataTableEditor extends DataTablesEditor
13
 class PiattoDataTableEditor extends DataTablesEditor
16
 {
14
 {
94
 
92
 
95
   public function creating(Model $model, array $data): array
93
   public function creating(Model $model, array $data): array
96
   {
94
   {
95
+    $data['attivita_id'] = Session::get('attivita_attuale');
96
+    AttivitaService::garantisciAttivita($data['attivita_id']);
97
+    $this->garantisciCucinaDiQuestaAttivita($data['cucina_id'] ?? null, $data['attivita_id']);
98
+
97
     // L'Editor manda `allergeni` come array di ID selezionati:
99
     // L'Editor manda `allergeni` come array di ID selezionati:
98
     // salviamo la relazione nella pivot `piatto_allergene`, non nella colonna `piatto.allergeni`.
100
     // salviamo la relazione nella pivot `piatto_allergene`, non nella colonna `piatto.allergeni`.
99
     $data['_allergeni_ids'] = $this->normalizeAllergeniIds($data['allergeni'] ?? null);
101
     $data['_allergeni_ids'] = $this->normalizeAllergeniIds($data['allergeni'] ?? null);
101
 
103
 
102
     $data['bacheca_id'] = isset($data['bacheca_id']) ? true : false;
104
     $data['bacheca_id'] = isset($data['bacheca_id']) ? true : false;
103
     $data['in_evidenza'] = isset($data['in_evidenza']) ? true : false;
105
     $data['in_evidenza'] = isset($data['in_evidenza']) ? true : false;
104
-    $data['disponibile'] = isset($data['disponibile']) ? true : false;
106
+    $data['is_attivo'] = isset($data['is_attivo']) ? true : false;
105
     return $data;
107
     return $data;
106
   }
108
   }
107
 
109
 
108
   public function updating(Model $model, array $data): array
110
   public function updating(Model $model, array $data): array
109
   {
111
   {
112
+    AttivitaService::garantisciAttivita($model->attivita_id);
113
+    unset($data['attivita_id']);
114
+    $this->garantisciCucinaDiQuestaAttivita($data['cucina_id'] ?? $model->cucina_id, $model->attivita_id);
115
+
110
     $data['_allergeni_ids'] = $this->normalizeAllergeniIds($data['allergeni'] ?? null);
116
     $data['_allergeni_ids'] = $this->normalizeAllergeniIds($data['allergeni'] ?? null);
111
     unset($data['allergeni']);
117
     unset($data['allergeni']);
112
 
118
 
113
     $data['bacheca_id'] = isset($data['bacheca_id']) ? true : false;
119
     $data['bacheca_id'] = isset($data['bacheca_id']) ? true : false;
114
     $data['in_evidenza'] = isset($data['in_evidenza']) ? true : false;
120
     $data['in_evidenza'] = isset($data['in_evidenza']) ? true : false;
115
-    $data['disponibile'] = isset($data['disponibile']) ? true : false;
121
+    $data['is_attivo'] = isset($data['is_attivo']) ? true : false;
116
 
122
 
117
     return $data;
123
     return $data;
118
   }
124
   }
119
 
125
 
126
+  public function deleting(Model $model, array $data): array
127
+  {
128
+    AttivitaService::garantisciAttivita($model->attivita_id);
129
+
130
+    return $data;
131
+  }
132
+
133
+  private function garantisciCucinaDiQuestaAttivita($cucinaId, $attivitaId): void
134
+  {
135
+    $cucina = Cucina::find($cucinaId);
136
+    if (! $cucina || (int) $cucina->attivita_id !== (int) $attivitaId) {
137
+      abort(404);
138
+    }
139
+  }
140
+
120
   protected function normalizeAllergeniIds(null|array|string $value): array
141
   protected function normalizeAllergeniIds(null|array|string $value): array
121
   {
142
   {
122
     if (is_null($value)) {
143
     if (is_null($value)) {

+ 8
- 1
app/DataTables/PuntoVenditaDataTable.php Просмотреть файл

16
 
16
 
17
 class PuntoVenditaDataTable extends DataTable
17
 class PuntoVenditaDataTable extends DataTable
18
 {
18
 {
19
+    public ?int $attivita_id = null;
20
+
19
     public function __construct()
21
     public function __construct()
20
     {
22
     {
21
         $this->dataTableVariable = 'dataTable_punto_vendita';
23
         $this->dataTableVariable = 'dataTable_punto_vendita';
83
      */
85
      */
84
     public function query(Dispositivo $model): QueryBuilder
86
     public function query(Dispositivo $model): QueryBuilder
85
     {
87
     {
88
+        $attivitaId = (int) $this->attivita_id;
89
+        if ($attivitaId <= 0) {
90
+            return $model->newQuery()->whereRaw('1 = 0');
91
+        }
92
+
86
         return $model->newQuery()
93
         return $model->newQuery()
87
         ->whereIn('tipo', [Dispositivo::KIOSK, Dispositivo::CASSA , Dispositivo::CAMERIERE])
94
         ->whereIn('tipo', [Dispositivo::KIOSK, Dispositivo::CASSA , Dispositivo::CAMERIERE])
88
-        ->where('attivita_id', $this->attivita_id);
95
+        ->where('attivita_id', $attivitaId);
89
     }
96
     }
90
 
97
 
91
     /**
98
     /**

+ 17
- 14
app/DataTables/PuntoVenditaDataTableEditor.php Просмотреть файл

3
 namespace App\DataTables;
3
 namespace App\DataTables;
4
 
4
 
5
 use App\Models\Dispositivo;
5
 use App\Models\Dispositivo;
6
+use App\Services\Attivita\AttivitaService;
6
 use Illuminate\Database\Eloquent\Model;
7
 use Illuminate\Database\Eloquent\Model;
7
-use Illuminate\Validation\Rule;
8
+use Illuminate\Support\Facades\Session;
8
 use Yajra\DataTables\DataTablesEditor;
9
 use Yajra\DataTables\DataTablesEditor;
9
-use Illuminate\Http\Request;
10
-use Illuminate\Validation\ValidationException;
11
-use Storage;
12
-use Illuminate\Support\Str;
13
 
10
 
14
 class PuntoVenditaDataTableEditor extends DataTablesEditor
11
 class PuntoVenditaDataTableEditor extends DataTablesEditor
15
 {
12
 {
49
   {
46
   {
50
     return [
47
     return [
51
       'nome'  => 'required',
48
       'nome'  => 'required',
52
-      'tipo' => 'required',
53
-      'attivita_id' => 'required|exists:attivita,id',
49
+      'tipo' => 'required|in:'.implode(',', [Dispositivo::CASSA, Dispositivo::KIOSK, Dispositivo::CAMERIERE]),
54
       'licenza' => 'nullable',
50
       'licenza' => 'nullable',
55
       'url_stampante' => 'nullable',
51
       'url_stampante' => 'nullable',
56
       'ubicazione' => 'nullable',
52
       'ubicazione' => 'nullable',
76
   {
72
   {
77
     return [
73
     return [
78
       'nome'  => 'required',
74
       'nome'  => 'required',
79
-      'tipo' => 'required',
80
-      'attivita_id' => 'required|exists:attivita,id',
75
+      'tipo' => 'required|in:'.implode(',', [Dispositivo::CASSA, Dispositivo::KIOSK, Dispositivo::CAMERIERE]),
81
       'licenza' => 'nullable',
76
       'licenza' => 'nullable',
82
       'url_stampante' => 'nullable',
77
       'url_stampante' => 'nullable',
83
       'ubicazione' => 'nullable',
78
       'ubicazione' => 'nullable',
106
 
101
 
107
   public function creating(Model $model, array $data): array
102
   public function creating(Model $model, array $data): array
108
   {
103
   {
109
-    // $model->roles()->sync([$data['ruolo_id']]);
110
-    $data['is_attiva'] = isset($data['is_attiva']) ? true : false;
104
+    $data['attivita_id'] = Session::get('attivita_attuale');
105
+    AttivitaService::garantisciAttivita($data['attivita_id']);
106
+    $data['is_attivo'] = isset($data['is_attivo']) ? true : false;
111
     return $data;
107
     return $data;
112
   }
108
   }
113
 
109
 
114
   public function updating(Model $model, array $data): array
110
   public function updating(Model $model, array $data): array
115
   {
111
   {
116
-    // dd($data['ruolo']);
117
-    // $model->roles()->sync([$data['ruolo_id']]);
118
-    $data['is_attiva'] = isset($data['is_attiva']) ? true : false;
112
+    AttivitaService::garantisciAttivita($model->attivita_id);
113
+    unset($data['attivita_id']);
114
+    $data['is_attivo'] = isset($data['is_attivo']) ? true : false;
115
+    return $data;
116
+  }
117
+
118
+  public function deleting(Model $model, array $data): array
119
+  {
120
+    AttivitaService::garantisciAttivita($model->attivita_id);
121
+
119
     return $data;
122
     return $data;
120
   }
123
   }
121
   public function messages(): array
124
   public function messages(): array

+ 13
- 0
app/Http/Controllers/AsportoController.php Просмотреть файл

3
 namespace App\Http\Controllers;
3
 namespace App\Http\Controllers;
4
 
4
 
5
 use Illuminate\Http\Request;
5
 use Illuminate\Http\Request;
6
+use Illuminate\Routing\Controllers\Middleware;
6
 use App\Models\Asporto;
7
 use App\Models\Asporto;
7
 use Illuminate\Support\Collection;
8
 use Illuminate\Support\Collection;
8
 
9
 
14
         'view-asporto' => 'Visualizza asporto',
15
         'view-asporto' => 'Visualizza asporto',
15
     ];
16
     ];
16
 
17
 
18
+    public static function middleware(): array
19
+    {
20
+        return [
21
+            new Middleware('permission:view-asporto', only: [
22
+                'index', 'dashboard', 'dashboard_slot',
23
+                'preparazione', 'completaPreparazione',
24
+                'chiamata', 'completaChiamata',
25
+                'ritiro', 'completaRitiro', 'sync',
26
+            ]),
27
+        ];
28
+    }
29
+
17
     public function index(Request $request)
30
     public function index(Request $request)
18
     {
31
     {
19
 
32
 

+ 114
- 72
app/Http/Controllers/CarrelloController.php Просмотреть файл

3
 namespace App\Http\Controllers;
3
 namespace App\Http\Controllers;
4
 
4
 
5
 use Illuminate\Http\Request;
5
 use Illuminate\Http\Request;
6
+use Illuminate\Routing\Controllers\Middleware;
6
 use App\Models\Ordine;
7
 use App\Models\Ordine;
7
-use App\Models\PuntoVendita;
8
+// use App\Models\PuntoVendita;
8
 use App\Models\Attivita;
9
 use App\Models\Attivita;
9
 use App\Models\Dispositivo;
10
 use App\Models\Dispositivo;
10
 use App\Models\Pagamento;
11
 use App\Models\Pagamento;
16
 use Illuminate\Support\Facades\Session;
17
 use Illuminate\Support\Facades\Session;
17
 use App\Http\Controllers\PagamentoController;
18
 use App\Http\Controllers\PagamentoController;
18
 use App\Services\Carrello\CarrelloService;
19
 use App\Services\Carrello\CarrelloService;
20
+use App\Services\Attivita\AttivitaService;
19
 
21
 
20
 class CarrelloController extends Controller
22
 class CarrelloController extends Controller
21
 {
23
 {
22
-
23
     private CarrelloService $carrelloService;
24
     private CarrelloService $carrelloService;
24
 
25
 
26
+    public static function middleware(): array
27
+    {
28
+        return [
29
+            new Middleware('permission:view-punto_vendita', only: [
30
+                'index', 'list', 'totale', 'checkout',
31
+                'aumenta', 'diminuisci', 'elimina', 'aggiorna_nota', 'azzera',
32
+                'aggiungi_variante', 'elimina_variante', 'aggiorna_info', 'paga_ordine',
33
+            ]),
34
+        ];
35
+    }
36
+
25
     public function __construct(CarrelloService $carrelloService)
37
     public function __construct(CarrelloService $carrelloService)
26
     {
38
     {
27
         $this->carrelloService = $carrelloService;
39
         $this->carrelloService = $carrelloService;
28
     }
40
     }
29
 
41
 
30
-    public function index(){
31
-        // return Ordine::all();
32
-        return Ordine::where('stato', Ordine::CARRELLO)->get();
33
-    }
42
+    public function index()
43
+    {
44
+        [$attivitaId, $dispositivoId] = $this->carrelloService->contestoCassa();
34
 
45
 
46
+        return Ordine::where('stato', Ordine::CARRELLO)
47
+            ->where('attivita_id', $attivitaId)
48
+            ->where('dispositivo_id', $dispositivoId)
49
+            ->get();
50
+    }
35
 
51
 
36
-    public function list(Request $request, RigaOrdineDataTable $dataTable){
52
+    public function list(Request $request, RigaOrdineDataTable $dataTable)
53
+    {
54
+        [$attivitaId, $dispositivoId] = $this->carrelloService->contestoCassa();
37
         $ordine = Ordine::where([
55
         $ordine = Ordine::where([
38
-            'stato' => Ordine::CARRELLO, 
39
-            'dispositivo_id' => Session::get('dispositivo_id') || $request->dispositivo_id,
40
-            'attivita_id' => Session::get('attivita_id') || $request->attivita_id,
56
+            'stato' => Ordine::CARRELLO,
57
+            'dispositivo_id' => $dispositivoId,
58
+            'attivita_id' => $attivitaId,
41
         ])->orderBy('created_at', 'desc')->first();
59
         ])->orderBy('created_at', 'desc')->first();
42
-    // dd($ordine->count());
60
+
43
         return $dataTable->render('punto_vendita.cassa._partials.carrello.index', ['ordine' => $ordine]);
61
         return $dataTable->render('punto_vendita.cassa._partials.carrello.index', ['ordine' => $ordine]);
44
     }
62
     }
45
 
63
 
46
-
47
-    public function aumenta(Request $request){
64
+    public function aumenta(Request $request)
65
+    {
48
         $request->validate([
66
         $request->validate([
49
             'ordine_id' => 'nullable|integer',
67
             'ordine_id' => 'nullable|integer',
50
             'piatto_id' => 'required|integer|exists:piatto,id',
68
             'piatto_id' => 'required|integer|exists:piatto,id',
51
-            'dispositivo_id' => 'required|integer|exists:dispositivo,id',
52
-            'attivita_id' => 'nullable|integer|exists:attivita,id',
53
             'riga_ordine_id' => 'nullable|integer|exists:riga_ordine,id',
69
             'riga_ordine_id' => 'nullable|integer|exists:riga_ordine,id',
54
         ]);
70
         ]);
55
-       
56
-       $result = $this->carrelloService->aumentaQuantita($request->dispositivo_id, $request->attivita_id, $request->ordine_id, $request->piatto_id, $request->riga_ordine_id);
57
-       $carrello = $result['ordine'];
58
-       $riga = $result['riga'];
59
 
71
 
60
-       return response()->json([
61
-           'success' => true,
62
-           'message' => 'Quantità aumentata',
63
-           'ordine_id' => $carrello->id,
64
-           'data' => $riga,
65
-       ]);
72
+        $result = $this->carrelloService->aumentaQuantita(
73
+            $request->filled('ordine_id') ? (int) $request->ordine_id : null,
74
+            (int) $request->piatto_id,
75
+            $request->filled('riga_ordine_id') ? (int) $request->riga_ordine_id : null
76
+        );
77
+        $carrello = $result['ordine'];
78
+        $riga = $result['riga'];
79
+
80
+        return response()->json([
81
+            'success' => true,
82
+            'message' => 'Quantità aumentata',
83
+            'ordine_id' => $carrello->id,
84
+            'data' => $riga,
85
+        ]);
66
 
86
 
67
 
87
 
68
         // Tolleranza su ordine_id stale: se non e` valido, usa/crea il carrello corrente per dispositivo+attivita.
88
         // Tolleranza su ordine_id stale: se non e` valido, usa/crea il carrello corrente per dispositivo+attivita.
278
         // // }
298
         // // }
279
     }
299
     }
280
 
300
 
281
-    public function totale(Request $request){
282
-        $ordine = Ordine::find($request->ordine_id);
283
-        if ($ordine == null){ 
301
+    public function totale(Request $request)
302
+    {
303
+        if (! $request->filled('ordine_id')) {
284
             return response()->json([
304
             return response()->json([
285
                 'success' => true,
305
                 'success' => true,
286
                 'message' => 'Totale carrello',
306
                 'message' => 'Totale carrello',
289
                 'quantita_totale' => 0,
309
                 'quantita_totale' => 0,
290
             ]);
310
             ]);
291
         }
311
         }
312
+
313
+        $ordine = $this->carrelloService->carrelloDiQuestaCassa((int) $request->ordine_id);
292
         // dd([$ordine->prezzo , $request->all()]);
314
         // dd([$ordine->prezzo , $request->all()]);
293
         if($ordine->prezzo == null || $ordine->prezzo == 0){
315
         if($ordine->prezzo == null || $ordine->prezzo == 0){
294
             if($ordine->righe_ordine->count() >0){
316
             if($ordine->righe_ordine->count() >0){
310
             'quantita_totale' => $quantitaTotale,
332
             'quantita_totale' => $quantitaTotale,
311
         ]);
333
         ]);
312
     }
334
     }
313
-    public function aggiorna_info(Request $request){
314
-        $ordine = Ordine::find($request->ordine_id);
315
-        if($ordine == null){
316
-            return response()->json([
317
-                'success' => false,
318
-                'message' => 'Ordine non trovato',
319
-                'data' => null,
320
-            ]);
321
-        }
335
+    public function aggiorna_info(Request $request)
336
+    {
337
+        $request->validate([
338
+            'ordine_id' => 'required|integer',
339
+        ]);
340
+        $ordine = $this->carrelloService->carrelloDiQuestaCassa((int) $request->ordine_id);
322
         $info = is_array($ordine->info) ? $ordine->info : [];
341
         $info = is_array($ordine->info) ? $ordine->info : [];
323
         $info['cliente'] = $request->cliente;
342
         $info['cliente'] = $request->cliente;
324
         $info['tavolo'] = $request->tavolo;
343
         $info['tavolo'] = $request->tavolo;
333
     }
352
     }
334
 
353
 
335
 
354
 
336
-    public function checkout(Request $request){
337
-        // $ordineA = Ordine::where([
338
-        //     'stato' => Ordine::CARRELLO, 
339
-        //     // 'dispositivo_id' => Session::get('dispositivo_id') || $request->dispositivo_id,
340
-        //     'attivita_id' => Session::get('attivita_id') || $request->attivita_id,
341
-        // ])->orderBy('created_at', 'desc')->first();
342
-        $ordine = Ordine::find($request->ordine_id);
343
-        if($ordine == null){
344
-            return  response()->json([
345
-                'success' => false,
346
-                'message' => 'Ordine non trovato',
347
-                'data' => null,
348
-                'ordineA' => $ordineA,
349
-                'ordineB' => $ordineB,
350
-                // 'ordineA->id == ordineB->id' => $ordineA->id == $ordineB->id,
351
-            ]);
352
-        }
355
+    public function checkout(Request $request)
356
+    {
357
+        $ordine = $this->carrelloService->carrelloDiQuestaCassa((int) $request->ordine_id);
353
 
358
 
354
         $ordine->prezzo = $ordine->righe_ordine->sum('prezzo');
359
         $ordine->prezzo = $ordine->righe_ordine->sum('prezzo');
355
         // $ordine->stato = Ordine::CHECKOUT;
360
         // $ordine->stato = Ordine::CHECKOUT;
361
     }
366
     }
362
 
367
 
363
     public function paga_ordine(Request $request){
368
     public function paga_ordine(Request $request){
369
+
364
         
370
         
365
-        if(!$request->filled('tag_id') && MetodoPagamento::find($request->metodo_pagamento_id)->tipo == MetodoPagamento::SEGRESTA_WALLET){
366
-            return back()->with('error', 'Tag ID obbligatorio per il metodo di pagamento Segresta Wallet');
371
+        $ordine = $this->carrelloService->carrelloDiQuestaCassa((int) $request->ordine_id);
372
+
373
+        $attivitaId = (int) (session('attivita_attuale') ?: session('attivita_id'));
374
+        $dispositivoId = (int) session('dispositivo_id');
375
+
376
+
377
+        if ($ordine->stato !== Ordine::CARRELLO) {
378
+            return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id , 'vista' => $request->vista])->with('error', 'Questo ordine non è più un carrello');
367
         }
379
         }
368
-        
369
-        $ordine = Ordine::find($request->ordine_id);
370
-        if($ordine == null){
371
-            return response()->json([
372
-                'success' => false,
373
-                'message' => 'Ordine non trovato',
374
-                'data' => null,
375
-            ]);
380
+
381
+        $metodo = MetodoPagamento::where('id', $request->metodo_pagamento_id)
382
+                ->where('attivita_id', $attivitaId)
383
+                ->where('is_attivo', true)
384
+                ->first();
385
+        if (! $metodo) {
386
+            return back()->with('error', 'Metodo di pagamento non valido');
387
+        }
388
+
389
+                
390
+        if(!$request->filled('tag_id') && $metodo->tipo == MetodoPagamento::SEGRESTA_WALLET){
391
+            return back()->with('error', 'Tag ID obbligatorio per il metodo di pagamento Segresta Wallet');
376
         }
392
         }
393
+
377
         $pagamento = Pagamento::create([
394
         $pagamento = Pagamento::create([
378
-            'attivita_id' => session('attivita_id'), //$request->attivita_id,
379
-            'dispositivo_id' => $request->dispositivo_id,
395
+            'attivita_id' => $attivitaId,
396
+            'dispositivo_id' => $dispositivoId,
380
             'ordine_id' => $ordine->id,
397
             'ordine_id' => $ordine->id,
381
             'metodo_pagamento_id' => $request->metodo_pagamento_id,
398
             'metodo_pagamento_id' => $request->metodo_pagamento_id,
382
             'tipo' => $request->tipo,
399
             'tipo' => $request->tipo,
406
                     $ordine->update(['stato' => Ordine::PAGATO]);
423
                     $ordine->update(['stato' => Ordine::PAGATO]);
407
                     return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id , 'vista' => $request->vista])->with('success', 'Pagamento con contanti riuscito. ->'.$pagamento->metodo_pagamento->tipo);
424
                     return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id , 'vista' => $request->vista])->with('success', 'Pagamento con contanti riuscito. ->'.$pagamento->metodo_pagamento->tipo);
408
                 }else{
425
                 }else{
426
+                    $pagamento->stato = Pagamento::ERRORE;
427
+                    $pagamento->save();
428
+
409
                     $ordine->stato = Ordine::CARRELLO;
429
                     $ordine->stato = Ordine::CARRELLO;
410
                     $ordine->save();
430
                     $ordine->save();
411
                     return back()->with('error', 'Pagamento con contanti non riuscito. '.$pagamentoResult['message']);
431
                     return back()->with('error', 'Pagamento con contanti non riuscito. '.$pagamentoResult['message']);
417
                 // $pagamento->save();
437
                 // $pagamento->save();
418
                 // return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con bonifico riuscito.');
438
                 // return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con bonifico riuscito.');
419
                 
439
                 
440
+                $pagamento->stato = Pagamento::ERRORE;
441
+                $pagamento->save();
442
+
420
                 $ordine->stato = Ordine::CARRELLO;
443
                 $ordine->stato = Ordine::CARRELLO;
421
                     $ordine->save();
444
                     $ordine->save();
422
                     return back()->with('error', 'METODO PAGAMENTO NON DISPONIBILE. ');
445
                     return back()->with('error', 'METODO PAGAMENTO NON DISPONIBILE. ');
426
                 // $pagamento->update(['stato' , Pagamento::PAGATO]);
449
                 // $pagamento->update(['stato' , Pagamento::PAGATO]);
427
                 // $pagamento->save();
450
                 // $pagamento->save();
428
                 // return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con paypal riuscito.');
451
                 // return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con paypal riuscito.');
429
-                
452
+                $pagamento->stato = Pagamento::ERRORE;
453
+                $pagamento->save();
454
+
430
                 $ordine->stato = Ordine::CARRELLO;
455
                 $ordine->stato = Ordine::CARRELLO;
431
                     $ordine->save();
456
                     $ordine->save();
432
                     return back()->with('error', 'METODO PAGAMENTO NON DISPONIBILE. ');
457
                     return back()->with('error', 'METODO PAGAMENTO NON DISPONIBILE. ');
436
                 // $pagamento->update(['stato' , Pagamento::PAGATO]);
461
                 // $pagamento->update(['stato' , Pagamento::PAGATO]);
437
                 // $pagamento->save();
462
                 // $pagamento->save();
438
                 // return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con carta di debito riuscito.');
463
                 // return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con carta di debito riuscito.');
439
-                
464
+                $pagamento->stato = Pagamento::ERRORE;
465
+                $pagamento->save();
466
+
440
                 $ordine->stato = Ordine::CARRELLO;
467
                 $ordine->stato = Ordine::CARRELLO;
441
                     $ordine->save();
468
                     $ordine->save();
442
                     return back()->with('error', 'METODO PAGAMENTO NON DISPONIBILE. ');
469
                     return back()->with('error', 'METODO PAGAMENTO NON DISPONIBILE. ');
443
 
470
 
444
                 break;
471
                 break;
445
             case MetodoPagamento::CUPON:
472
             case MetodoPagamento::CUPON:
446
-                $pagamentoResult = app('\App\Services\Paga\Cupon')->paga($pagamento);
473
+                $pagamentoResult = app('\App\Services\Paga\PagaCupon')->paga($pagamento, $request->cupon_codice);
447
                 
474
                 
448
                 if($pagamentoResult['result'] === true){
475
                 if($pagamentoResult['result'] === true){
449
                     $ordine->update(['stato' => Ordine::PAGATO]);
476
                     $ordine->update(['stato' => Ordine::PAGATO]);
450
                     return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con cupon riuscito.');
477
                     return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con cupon riuscito.');
451
                 }else{
478
                 }else{
479
+                    $pagamento->stato = Pagamento::ERRORE;
480
+                    $pagamento->save();
481
+
452
                     $ordine->stato = Ordine::CARRELLO;
482
                     $ordine->stato = Ordine::CARRELLO;
453
                     $ordine->save();
483
                     $ordine->save();
454
                     return back()->with('error', 'Pagamento con cupon non riuscito. '.$pagamentoResult['message']);
484
                     return back()->with('error', 'Pagamento con cupon non riuscito. '.$pagamentoResult['message']);
460
                 
490
                 
461
                 if($pagamentoResult['result'] === true){
491
                 if($pagamentoResult['result'] === true){
462
                     $pagamento->update(['stato' => Pagamento::PAGATO]);
492
                     $pagamento->update(['stato' => Pagamento::PAGATO]);
463
-                    $pagamento->save();
493
+                    $ordine->update(['stato' => Ordine::PAGATO]);
494
+
464
                     return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con wallet riuscito.');
495
                     return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con wallet riuscito.');
465
                 }else{
496
                 }else{
466
                     $pagamento->stato = Pagamento::ERRORE;
497
                     $pagamento->stato = Pagamento::ERRORE;
475
                     // $pagamento->update(['stato' , Pagamento::PAGATO]);
506
                     // $pagamento->update(['stato' , Pagamento::PAGATO]);
476
                     // $pagamento->save();
507
                     // $pagamento->save();
477
                     // return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con apple pay riuscito.');
508
                     // return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con apple pay riuscito.');
478
-                    
509
+                    $pagamento->stato = Pagamento::ERRORE;
510
+                    $pagamento->save();
511
+
479
                     $ordine->stato = Ordine::CARRELLO;
512
                     $ordine->stato = Ordine::CARRELLO;
480
                     $ordine->save();
513
                     $ordine->save();
481
                     return back()->with('error', 'METODO PAGAMENTO NON DISPONIBILE. ');
514
                     return back()->with('error', 'METODO PAGAMENTO NON DISPONIBILE. ');
485
                 // $pagamento->update(['stato' , Pagamento::PAGATO]);
518
                 // $pagamento->update(['stato' , Pagamento::PAGATO]);
486
                 // $pagamento->save();
519
                 // $pagamento->save();
487
                 // return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con google pay riuscito.');
520
                 // return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con google pay riuscito.');
488
-                
521
+                $pagamento->stato = Pagamento::ERRORE;
522
+                $pagamento->save();
523
+
489
                 $ordine->stato = Ordine::CARRELLO;
524
                 $ordine->stato = Ordine::CARRELLO;
490
                     $ordine->save();
525
                     $ordine->save();
491
                     return back()->with('error', 'METODO PAGAMENTO NON DISPONIBILE. ');
526
                     return back()->with('error', 'METODO PAGAMENTO NON DISPONIBILE. ');
498
                     $ordine->update(['stato' => Ordine::PAGATO]);
533
                     $ordine->update(['stato' => Ordine::PAGATO]);
499
                     return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con contanti riuscito. ->'.$pagamento->metodo_pagamento->tipo);
534
                     return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con contanti riuscito. ->'.$pagamento->metodo_pagamento->tipo);
500
                 }else{
535
                 }else{
536
+                    $pagamento->stato = Pagamento::ERRORE;
537
+                    $pagamento->save();
538
+
501
                     $ordine->stato = Ordine::CARRELLO;
539
                     $ordine->stato = Ordine::CARRELLO;
502
                     $ordine->save();
540
                     $ordine->save();
503
                     return back()->with('error', 'Pagamento con contanti non riuscito. '.$pagamentoResult['message']);
541
                     return back()->with('error', 'Pagamento con contanti non riuscito. '.$pagamentoResult['message']);
504
                 }
542
                 }
543
+                break;
505
 
544
 
506
             case MetodoPagamento::STAFF:
545
             case MetodoPagamento::STAFF:
507
                 $pagamentoResult = app('\App\Services\Paga\Staff')->paga($pagamento);
546
                 $pagamentoResult = app('\App\Services\Paga\Staff')->paga($pagamento);
510
                     $ordine->update(['stato' => Ordine::PAGATO]);
549
                     $ordine->update(['stato' => Ordine::PAGATO]);
511
                     return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con staff riuscito.');
550
                     return redirect()->route('punto-vendita.show', ['punto_vendita_id' => $ordine->dispositivo_id])->with('success', 'Pagamento con staff riuscito.');
512
                 }else{
551
                 }else{
552
+                    $pagamento->stato = Pagamento::ERRORE;
553
+                    $pagamento->save();
554
+
513
                     $ordine->stato = Ordine::CARRELLO;
555
                     $ordine->stato = Ordine::CARRELLO;
514
                     $ordine->save();
556
                     $ordine->save();
515
                     return back()->with('error', 'Pagamento con staff non riuscito. '.$pagamentoResult['message']);
557
                     return back()->with('error', 'Pagamento con staff non riuscito. '.$pagamentoResult['message']);

+ 26
- 3
app/Http/Controllers/OperatoreController.php Просмотреть файл

8
 use App\DataTables\OperatoreDataTableEditor;
8
 use App\DataTables\OperatoreDataTableEditor;
9
 use Illuminate\Support\Facades\Auth;
9
 use Illuminate\Support\Facades\Auth;
10
 use Illuminate\Routing\Controllers\Middleware;
10
 use Illuminate\Routing\Controllers\Middleware;
11
-use Illuminate\Routing\Controllers\HasMiddleware;
12
 use Illuminate\Support\Facades\Hash;
11
 use Illuminate\Support\Facades\Hash;
13
 use Illuminate\Support\Facades\Validator;
12
 use Illuminate\Support\Facades\Validator;
14
 use Illuminate\Support\Str;
13
 use Illuminate\Support\Str;
17
 use App\Models\Ordine;
16
 use App\Models\Ordine;
18
 use Illuminate\Support\Facades\Session;
17
 use Illuminate\Support\Facades\Session;
19
 use App\DataTables\RigaOrdineDataTable;
18
 use App\DataTables\RigaOrdineDataTable;
19
+use App\Services\Attivita\AttivitaService;
20
 
20
 
21
 
21
 
22
 class OperatoreController extends Controller
22
 class OperatoreController extends Controller
32
     public static function middleware(): array
32
     public static function middleware(): array
33
     {
33
     {
34
         return [
34
         return [
35
-            new Middleware('permission:view-operatore', only: ['index']),
36
-            new Middleware('permission:create-operatore|edit-operatore|delete-operatore', only: ['store', 'update', 'destroy']),
35
+            new Middleware('permission:view-operatore', only: ['index', 'show']),
36
+            new Middleware('permission:create-operatore|edit-operatore|delete-operatore', only: ['store', 'update', 'destroy', 'update_password', 'update_dispositivi']),
37
         ];
37
         ];
38
     }
38
     }
39
     
39
     
50
         if (!$operatore) {
50
         if (!$operatore) {
51
             return redirect()->back()->with('error', 'Operatore non trovato');
51
             return redirect()->back()->with('error', 'Operatore non trovato');
52
         }
52
         }
53
+        AttivitaService::garantisciAttivita($operatore->attivita_id);
53
         return view('operatore.show', ['operatore' => $operatore , 'dispositivi' => $operatore->dispositivi]);
54
         return view('operatore.show', ['operatore' => $operatore , 'dispositivi' => $operatore->dispositivi]);
54
     }
55
     }
55
 
56
 
56
     public function update_password(Request $request)
57
     public function update_password(Request $request)
57
     {
58
     {
58
         $operatore = Operatore::find($request->get('operatore_id'));
59
         $operatore = Operatore::find($request->get('operatore_id'));
60
+        if (!$operatore) {
61
+            return redirect()->back()->with('error', 'Operatore non trovato');
62
+        }
63
+        AttivitaService::garantisciAttivita($operatore->attivita_id);
59
         $operatore->password = Hash::make($request->get('password'));
64
         $operatore->password = Hash::make($request->get('password'));
60
         $operatore->save();
65
         $operatore->save();
61
         return redirect()->route('operatore.show', ['operatore_id' => $operatore->id])->with('success', 'Password aggiornata con successo');
66
         return redirect()->route('operatore.show', ['operatore_id' => $operatore->id])->with('success', 'Password aggiornata con successo');
78
         if (!$operatore) {
83
         if (!$operatore) {
79
             return redirect()->back()->with('error', 'Operatore non trovato');
84
             return redirect()->back()->with('error', 'Operatore non trovato');
80
         }
85
         }
86
+        AttivitaService::garantisciAttivita($operatore->attivita_id);
87
+
88
+        $ids = array_values(array_unique(array_map('intval', $ids)));
89
+        if ($ids !== []) {
90
+            $dispositivi = Dispositivo::query()->whereIn('id', $ids)->get();
91
+            if ($dispositivi->count() !== count($ids)
92
+                || $dispositivi->contains(fn ($dispositivo) => (int) $dispositivo->attivita_id !== (int) $operatore->attivita_id)
93
+            ) {
94
+                abort(404);
95
+            }
96
+        }
81
 
97
 
82
         $operatore->dispositivi()->sync($ids);
98
         $operatore->dispositivi()->sync($ids);
83
 
99
 
174
             return redirect()->route('punto-vendita.index')
190
             return redirect()->route('punto-vendita.index')
175
             ->with('error', 'Punto di vendita non trovato');
191
             ->with('error', 'Punto di vendita non trovato');
176
         }
192
         }
193
+        $operatore = Auth::guard('operatore')->user();
194
+        if (! $operatore
195
+            || (int) $puntoVendita->attivita_id !== (int) $operatore->attivita_id
196
+            || ! $operatore->dispositivi()->where('dispositivo.id', $puntoVendita->id)->exists()
197
+        ) {
198
+            return redirect()->route('operatore.landing')->with('error', 'Non sei autorizzato a accedere a questo dispositivo');
199
+        }
177
 // dd('A',$puntoVendita);
200
 // dd('A',$puntoVendita);
178
         if($puntoVendita->binding_token == '' || $puntoVendita->binding_token == null ){
201
         if($puntoVendita->binding_token == '' || $puntoVendita->binding_token == null ){
179
             $puntoVendita->binding_token = Hash::make(Str::random(32));
202
             $puntoVendita->binding_token = Hash::make(Str::random(32));

+ 24
- 2
app/Http/Controllers/OrdineController.php Просмотреть файл

2
 
2
 
3
 namespace App\Http\Controllers;
3
 namespace App\Http\Controllers;
4
 
4
 
5
+
6
+use Illuminate\Routing\Controllers\Middleware;
5
 use Illuminate\Http\Request;
7
 use Illuminate\Http\Request;
6
 use App\Models\Ordine;
8
 use App\Models\Ordine;
7
 use App\DataTables\OrdineDataTable;
9
 use App\DataTables\OrdineDataTable;
8
 use App\DataTables\OrdineDataTableEditor;
10
 use App\DataTables\OrdineDataTableEditor;
9
 use Illuminate\Support\Facades\Auth;
11
 use Illuminate\Support\Facades\Auth;
12
+use App\Services\Attivita\AttivitaService;
10
 
13
 
11
 class OrdineController extends Controller
14
 class OrdineController extends Controller
12
 {
15
 {
21
     public static function middleware(): array
24
     public static function middleware(): array
22
     {
25
     {
23
         return [
26
         return [
24
-            new Middleware('permission:view-ordine', only: ['index']),
27
+            new Middleware('permission:view-ordine', only: ['index', 'show', 'show_modal']),
25
             new Middleware('permission:create-ordine|edit-ordine|delete-ordine', only: ['store', 'update', 'destroy']),
28
             new Middleware('permission:create-ordine|edit-ordine|delete-ordine', only: ['store', 'update', 'destroy']),
26
         ];
29
         ];
27
     }
30
     }
53
 
56
 
54
     public function show(Request $request)
57
     public function show(Request $request)
55
     {
58
     {
56
-        $ordine = Ordine::find($request->get('ordine_id'));
59
+        $ordine = Ordine::with([
60
+            'dispositivo',
61
+            'attivita',
62
+            'prenotazione',
63
+            'pagamenti.metodo_pagamento',
64
+            'asporto',
65
+            'righe_ordine.piatto.cucina',
66
+            'righe_ordine.piatto.elencoAllergeni',
67
+            'righe_ordine.has_variante.variante_piatto',
68
+        ])->find($request->get('ordine_id'));
69
+        if (! $ordine) {
70
+            abort(404);
71
+        }
72
+        AttivitaService::garantisciAttivita($ordine->attivita_id);
73
+
57
         return view('ordine.show', compact('ordine'));
74
         return view('ordine.show', compact('ordine'));
58
     }
75
     }
59
 
76
 
60
     public function show_modal(Request $request)
77
     public function show_modal(Request $request)
61
     {
78
     {
62
         $ordine = Ordine::find($request->get('ordine_id'));
79
         $ordine = Ordine::find($request->get('ordine_id'));
80
+        if (! $ordine) {
81
+            abort(404);
82
+        }
83
+        AttivitaService::garantisciAttivita($ordine->attivita_id);
84
+
63
         return view('ordine.show_modal', compact('ordine'));
85
         return view('ordine.show_modal', compact('ordine'));
64
     }
86
     }
65
 }
87
 }

+ 10
- 1
app/Http/Controllers/PiattoController.php Просмотреть файл

2
 
2
 
3
 namespace App\Http\Controllers;
3
 namespace App\Http\Controllers;
4
 
4
 
5
+
6
+use Illuminate\Routing\Controllers\Middleware;
5
 use Illuminate\Http\Request;
7
 use Illuminate\Http\Request;
6
 use App\Models\Piatto;
8
 use App\Models\Piatto;
7
 use App\Models\PiattoHasAllergene;
9
 use App\Models\PiattoHasAllergene;
9
 use App\DataTables\PiattoDataTableEditor;
11
 use App\DataTables\PiattoDataTableEditor;
10
 use Illuminate\Support\Facades\Auth;
12
 use Illuminate\Support\Facades\Auth;
11
 use Illuminate\Support\Facades\Session;
13
 use Illuminate\Support\Facades\Session;
14
+use App\Services\Attivita\AttivitaService;
12
 
15
 
13
 class PiattoController extends Controller
16
 class PiattoController extends Controller
14
 {
17
 {
23
     public static function middleware(): array
26
     public static function middleware(): array
24
     {
27
     {
25
         return [
28
         return [
26
-            new Middleware('permission:view-piatto', only: ['index']),
29
+            new Middleware('permission:view-piatto', only: ['index', 'datatable']),
27
             new Middleware('permission:create-piatto|edit-piatto|delete-piatto', only: ['store', 'update', 'destroy']),
30
             new Middleware('permission:create-piatto|edit-piatto|delete-piatto', only: ['store', 'update', 'destroy']),
28
         ];
31
         ];
29
     }
32
     }
100
 
103
 
101
       foreach ($payload as $piattoId => $data) {
104
       foreach ($payload as $piattoId => $data) {
102
         $piattoId = (int) $piattoId;
105
         $piattoId = (int) $piattoId;
106
+        $piatto = Piatto::find($piattoId);
107
+        if (! $piatto) {
108
+          abort(404);
109
+        }
110
+        AttivitaService::garantisciAttivita($piatto->attivita_id);
111
+
103
         $allergenIds = $data['allergeni'] ?? [];
112
         $allergenIds = $data['allergeni'] ?? [];
104
 
113
 
105
         if (is_string($allergenIds)) {
114
         if (is_string($allergenIds)) {

+ 6
- 1
app/Http/Controllers/PuntoOperatoreController.php Просмотреть файл

2
 
2
 
3
 namespace App\Http\Controllers;
3
 namespace App\Http\Controllers;
4
 
4
 
5
+
6
+use Illuminate\Routing\Controllers\Middleware;
5
 use Illuminate\Http\Request;
7
 use Illuminate\Http\Request;
6
 use App\Models\Dispositivo;
8
 use App\Models\Dispositivo;
7
 use App\DataTables\PuntoOperatoreDataTable;
9
 use App\DataTables\PuntoOperatoreDataTable;
8
 use App\DataTables\PuntoOperatoreDataTableEditor;
10
 use App\DataTables\PuntoOperatoreDataTableEditor;
9
 use Illuminate\Support\Facades\Auth;
11
 use Illuminate\Support\Facades\Auth;
12
+use App\Services\Attivita\AttivitaService;
10
 
13
 
11
 class PuntoOperatoreController extends Controller
14
 class PuntoOperatoreController extends Controller
12
 {
15
 {
22
     public static function middleware(): array
25
     public static function middleware(): array
23
     {
26
     {
24
         return [
27
         return [
25
-            new Middleware('permission:view-punto_operatore', only: ['index']),
28
+            new Middleware('permission:view-punto_operatore', only: ['index', 'show']),
26
             new Middleware('permission:edit-punto_operatore', only: ['toggle_is_attivo']),
29
             new Middleware('permission:edit-punto_operatore', only: ['toggle_is_attivo']),
27
             new Middleware('permission:create-punto_operatore|edit-punto_operatore|delete-punto_operatore', only: ['store', 'update', 'destroy']),
30
             new Middleware('permission:create-punto_operatore|edit-punto_operatore|delete-punto_operatore', only: ['store', 'update', 'destroy']),
28
         ];
31
         ];
67
         if(!$dispositivo){
70
         if(!$dispositivo){
68
             return redirect()->back()->with('error', 'Punto operatore non trovato');
71
             return redirect()->back()->with('error', 'Punto operatore non trovato');
69
         }
72
         }
73
+        AttivitaService::garantisciAttivita($dispositivo->attivita_id);
70
 
74
 
71
         $dispositivo->is_attivo = !$dispositivo->is_attivo;
75
         $dispositivo->is_attivo = !$dispositivo->is_attivo;
72
         $dispositivo->save();
76
         $dispositivo->save();
79
         if(!$dispositivo){
83
         if(!$dispositivo){
80
             return redirect()->back()->with('error', 'Punto operatore non trovato');
84
             return redirect()->back()->with('error', 'Punto operatore non trovato');
81
         }
85
         }
86
+        AttivitaService::garantisciAttivita($dispositivo->attivita_id);
82
         return view('punto_operatore.show', ['dispositivo' => $dispositivo]);
87
         return view('punto_operatore.show', ['dispositivo' => $dispositivo]);
83
     }
88
     }
84
 }
89
 }

+ 85
- 38
app/Http/Controllers/PuntoVenditaController.php Просмотреть файл

2
 
2
 
3
 namespace App\Http\Controllers;
3
 namespace App\Http\Controllers;
4
 
4
 
5
+
6
+use Illuminate\Routing\Controllers\Middleware;
5
 use App\DataTables\PuntoVenditaDataTable;
7
 use App\DataTables\PuntoVenditaDataTable;
6
 use App\DataTables\PuntoVenditaDataTableEditor;
8
 use App\DataTables\PuntoVenditaDataTableEditor;
7
 use App\DataTables\RigaOrdineDataTable;
9
 use App\DataTables\RigaOrdineDataTable;
8
 
10
 
9
 use App\Models\Dispositivo;
11
 use App\Models\Dispositivo;
12
+use App\Models\Cucina;
10
 use App\Models\Ordine;
13
 use App\Models\Ordine;
11
 use App\Models\Pagamento;
14
 use App\Models\Pagamento;
12
 use App\Models\RigaOrdine;
15
 use App\Models\RigaOrdine;
14
 use App\Models\SaltacodaOrdine;
17
 use App\Models\SaltacodaOrdine;
15
 use App\Models\SaltacodaRigaOrdine;
18
 use App\Models\SaltacodaRigaOrdine;
16
 use App\Models\SaltacodaRigaOrdineHasVariante;
19
 use App\Models\SaltacodaRigaOrdineHasVariante;
20
+use App\Services\Attivita\AttivitaService;
17
 
21
 
18
 use Illuminate\Support\Str;
22
 use Illuminate\Support\Str;
19
 use Illuminate\Http\Request;
23
 use Illuminate\Http\Request;
37
     public static function middleware(): array
41
     public static function middleware(): array
38
     {
42
     {
39
         return [
43
         return [
40
-            new Middleware('permission:view-punto_vendita', only: ['index', 'dettagli_punto_vendita', 'dettagli']),
41
-            new Middleware('permission:create-punto_vendita|edit-punto_vendita|delete-punto_vendita', only: ['store', 'update', 'destroy', 'edit', 'associa_cucina']),
44
+            new Middleware('permission:view-punto_vendita', only: [
45
+                'index', 'dettagli_punto_vendita', 'dettagli', 'show',
46
+                'riepilogo', 'riepilogo_cassa', 'cerca_pre_ordine',
47
+            ]),
48
+            new Middleware('permission:create-punto_vendita|edit-punto_vendita|delete-punto_vendita', only: [
49
+                'store', 'update', 'destroy', 'edit', 'associa_cucina',
50
+                'dissocia_dispositivo', 'importa_pre_ordine',
51
+            ]),
42
         ];
52
         ];
43
     }
53
     }
44
 
54
 
58
             return redirect()->route('punto-vendita.index')
68
             return redirect()->route('punto-vendita.index')
59
                 ->with('error', 'Punto di vendita non trovato');
69
                 ->with('error', 'Punto di vendita non trovato');
60
         }
70
         }
71
+        AttivitaService::garantisciAttivita($puntoVendita->attivita_id);
61
 
72
 
62
         return view('punto_vendita.dettaglio_punto_vendita', compact('puntoVendita'));
73
         return view('punto_vendita.dettaglio_punto_vendita', compact('puntoVendita'));
63
     }
74
     }
70
             return redirect()->route('punto-vendita.index')
81
             return redirect()->route('punto-vendita.index')
71
                 ->with('error', 'Punto di vendita non trovato');
82
                 ->with('error', 'Punto di vendita non trovato');
72
         }
83
         }
84
+        AttivitaService::garantisciAttivita($puntoVendita->attivita_id);
73
 
85
 
74
         return view('punto_vendita.edit', ['puntoVendita' => $puntoVendita]);
86
         return view('punto_vendita.edit', ['puntoVendita' => $puntoVendita]);
75
     }
87
     }
82
             return redirect()->route('punto-vendita.index')
94
             return redirect()->route('punto-vendita.index')
83
                 ->with('error', 'Punto di vendita non trovato');
95
                 ->with('error', 'Punto di vendita non trovato');
84
         }
96
         }
97
+        AttivitaService::garantisciAttivita($puntoVendita->attivita_id);
85
 
98
 
86
         if (Auth::user()->can('edit-punto_vendita')) {
99
         if (Auth::user()->can('edit-punto_vendita')) {
87
 
100
 
135
             //         }
148
             //         }
136
             // }
149
             // }
137
 
150
 
151
+            unset($validated['attivita_id']);
152
+
153
+            if (! empty($validated['endpoint_id'])) {
154
+                $endpoint = \App\Models\Endpoint::find($validated['endpoint_id']);
155
+                if (! $endpoint || (int) $endpoint->attivita_id !== (int) $puntoVendita->attivita_id) {
156
+                    abort(404);
157
+                }
158
+            }
159
+
138
             if ($request->has('info')) {
160
             if ($request->has('info')) {
139
                 $validated['info'] = json_decode($request->info, true);
161
                 $validated['info'] = json_decode($request->info, true);
140
             }
162
             }
141
             if ($request->has('url_stampante')) {
163
             if ($request->has('url_stampante')) {
142
-                $validated['endpoint_id'] = Dispositivo::where('id', $validated['url_stampante'])
143
-                    ->where('tipo', Dispositivo::STAMPANTE)->first()->endpoint_id ?? null;
144
-
164
+                $stampante = Dispositivo::where('id', $validated['url_stampante'])
165
+                    ->where('tipo', Dispositivo::STAMPANTE)
166
+                    ->where('attivita_id', $puntoVendita->attivita_id)
167
+                    ->first();
168
+                $validated['endpoint_id'] = $stampante->endpoint_id ?? null;
145
             }
169
             }
146
 
170
 
147
             $puntoVendita->update($validated);
171
             $puntoVendita->update($validated);
158
         if (! $puntoVendita) {
182
         if (! $puntoVendita) {
159
             return response()->json(['success' => false, 'message' => 'Punto di vendita non trovato']);
183
             return response()->json(['success' => false, 'message' => 'Punto di vendita non trovato']);
160
         }
184
         }
185
+        AttivitaService::garantisciAttivita($puntoVendita->attivita_id);
161
 
186
 
162
         if (Auth::user()->can('edit-punto_vendita')) {
187
         if (Auth::user()->can('edit-punto_vendita')) {
163
-            $cucine_ids = $request->get('cucine_ids');
188
+            $cucine_ids = array_values(array_filter(array_map('intval', (array) $request->get('cucine_ids', []))));
189
+            if ($cucine_ids !== []) {
190
+                $cucine = Cucina::query()
191
+                    ->whereIn('id', $cucine_ids)
192
+                    ->get();
193
+                if ($cucine->count() !== count($cucine_ids)
194
+                    || $cucine->contains(fn ($cucina) => (int) $cucina->attivita_id !== (int) $puntoVendita->attivita_id)
195
+                ) {
196
+                    abort(404);
197
+                }
198
+            }
164
             $puntoVendita->hasCucine()->sync($cucine_ids);
199
             $puntoVendita->hasCucine()->sync($cucine_ids);
165
 
200
 
166
             return response()->json(['success' => true, 'message' => 'Cucine associate con successo']);
201
             return response()->json(['success' => true, 'message' => 'Cucine associate con successo']);
210
             return redirect()->route('punto-vendita.index')
245
             return redirect()->route('punto-vendita.index')
211
                 ->with('error', 'Punto di vendita non trovato');
246
                 ->with('error', 'Punto di vendita non trovato');
212
         }
247
         }
213
-
248
+        AttivitaService::garantisciAttivita($puntoVendita->attivita_id);
249
+        
214
         if($puntoVendita->attivita->user_id != Auth::user()->id){
250
         if($puntoVendita->attivita->user_id != Auth::user()->id){
215
             session(['attivita_attuale' => null]);
251
             session(['attivita_attuale' => null]);
216
             Cookie::queue(Cookie::forget('binding_token'));
252
             Cookie::queue(Cookie::forget('binding_token'));
285
                     if ($isDataTableDrawRequest) {
321
                     if ($isDataTableDrawRequest) {
286
                         // Prosegue senza interrompere la risposta DataTable.
322
                         // Prosegue senza interrompere la risposta DataTable.
287
                     } else {
323
                     } else {
288
-                        dd('11, altro dispositivo', json_encode(request()->cookie()));
289
-
290
                         return redirect()->route('punto-vendita.index')->with('error', 'Dispositivo già occupato. Dissociare per potervi accedere.');
324
                         return redirect()->route('punto-vendita.index')->with('error', 'Dispositivo già occupato. Dissociare per potervi accedere.');
291
                     }
325
                     }
292
                 }
326
                 }
346
         if (! $puntoVendita) {
380
         if (! $puntoVendita) {
347
             return response()->json(['success' => false, 'message' => 'Punto di vendita non trovato']);
381
             return response()->json(['success' => false, 'message' => 'Punto di vendita non trovato']);
348
         }
382
         }
349
-
383
+        AttivitaService::garantisciAttivita($puntoVendita->attivita_id);
384
+        
350
         Cookie::queue(Cookie::forget('binding_token'));
385
         Cookie::queue(Cookie::forget('binding_token'));
351
 
386
 
352
         $puntoVendita->binding_token = null;
387
         $puntoVendita->binding_token = null;
363
             return redirect()->route('punto-vendita.kiosk.index')
398
             return redirect()->route('punto-vendita.kiosk.index')
364
                 ->with('error', 'Ordine non trovato');
399
                 ->with('error', 'Ordine non trovato');
365
         }
400
         }
401
+        AttivitaService::garantisciAttivita($ordine->attivita_id);
366
 
402
 
367
         return view('punto_vendita.kiosk.riepilogo', ['ordine' => $ordine]);
403
         return view('punto_vendita.kiosk.riepilogo', ['ordine' => $ordine]);
368
     }
404
     }
374
             return redirect()->route('punto-vendita.index')
410
             return redirect()->route('punto-vendita.index')
375
                 ->with('error', 'Punto di vendita non trovato');
411
                 ->with('error', 'Punto di vendita non trovato');
376
         }
412
         }
377
-
413
+        AttivitaService::garantisciAttivita($puntoVendita->attivita_id);
414
+        
378
         return view('punto_vendita.dettagli', ['puntoVendita' => $puntoVendita]);
415
         return view('punto_vendita.dettagli', ['puntoVendita' => $puntoVendita]);
379
     }
416
     }
380
 
417
 
385
             return redirect()->route('punto-vendita.index')
422
             return redirect()->route('punto-vendita.index')
386
                 ->with('error', 'Punto di vendita non trovato');
423
                 ->with('error', 'Punto di vendita non trovato');
387
         }
424
         }
388
-        // Calcola la data di oggi
425
+        AttivitaService::garantisciAttivita($puntoVendita->attivita_id);
426
+        
389
         $oggi = now()->startOfDay();
427
         $oggi = now()->startOfDay();
390
 
428
 
391
-        // Recupera tutti gli ordini di oggi per il punto vendita
392
-        $ordiniOggi = \App\Models\Ordine::where('dispositivo_id', $puntoVendita->id)
429
+        // Solo ordini effettivamente pagati (esclude carrelli e tentativi falliti)
430
+        $ordiniOggi = Ordine::query()
431
+            ->where('dispositivo_id', $puntoVendita->id)
432
+            ->where('stato', Ordine::PAGATO)
393
             ->whereDate('created_at', $oggi)
433
             ->whereDate('created_at', $oggi)
394
             ->get();
434
             ->get();
395
 
435
 
396
-        // Conta il totale ordini di oggi
397
         $totaleOrdiniOggi = $ordiniOggi->count();
436
         $totaleOrdiniOggi = $ordiniOggi->count();
398
-
399
         $ordineIds = $ordiniOggi->pluck('id')->all();
437
         $ordineIds = $ordiniOggi->pluck('id')->all();
400
 
438
 
401
         if ($ordineIds === []) {
439
         if ($ordineIds === []) {
403
             $pagamentiPerMetodo = [];
441
             $pagamentiPerMetodo = [];
404
             $pagamentiConteggioPerMetodo = [];
442
             $pagamentiConteggioPerMetodo = [];
405
         } else {
443
         } else {
406
-            // Somma importi pagamenti legati agli ordini di oggi di questo punto vendita
407
-            $totaleIncassi = (float) Pagamento::query()
444
+            // Solo pagamenti con stato "pagato" (scopePerIncasso)
445
+            $pagamentiBase = Pagamento::query()
408
                 ->whereIn('ordine_id', $ordineIds)
446
                 ->whereIn('ordine_id', $ordineIds)
409
-                ->sum('importo');
447
+                ->perIncasso();
410
 
448
 
411
-            // Raggruppa per metodo_pagamento_id (colonna reale su tabella pagamento)
412
-            $pagamentiPerMetodo = Pagamento::query()
413
-                ->whereIn('ordine_id', $ordineIds)
449
+            $totaleIncassi = (float) (clone $pagamentiBase)->sum('importo');
450
+
451
+            $pagamentiPerMetodo = (clone $pagamentiBase)
414
                 ->selectRaw('metodo_pagamento_id, SUM(importo) as totale_importo')
452
                 ->selectRaw('metodo_pagamento_id, SUM(importo) as totale_importo')
415
                 ->groupBy('metodo_pagamento_id')
453
                 ->groupBy('metodo_pagamento_id')
416
                 ->pluck('totale_importo', 'metodo_pagamento_id')
454
                 ->pluck('totale_importo', 'metodo_pagamento_id')
417
                 ->map(fn ($v) => (float) $v)
455
                 ->map(fn ($v) => (float) $v)
418
                 ->all();
456
                 ->all();
419
 
457
 
420
-            $pagamentiConteggioPerMetodo = Pagamento::query()
421
-                ->whereIn('ordine_id', $ordineIds)
458
+            $pagamentiConteggioPerMetodo = (clone $pagamentiBase)
422
                 ->selectRaw('metodo_pagamento_id, COUNT(*) as conteggio')
459
                 ->selectRaw('metodo_pagamento_id, COUNT(*) as conteggio')
423
                 ->groupBy('metodo_pagamento_id')
460
                 ->groupBy('metodo_pagamento_id')
424
                 ->pluck('conteggio', 'metodo_pagamento_id')
461
                 ->pluck('conteggio', 'metodo_pagamento_id')
438
     public function cerca_pre_ordine(Request $request)
475
     public function cerca_pre_ordine(Request $request)
439
     {
476
     {
440
         $codice = $request->get('codice');
477
         $codice = $request->get('codice');
441
-        // $pre_ordine = \App\Models\SaltacodaOrdine::where('codice' , $codice)->first();
442
-        // $pre_ordine = \App\Models\SaltacodaOrdine::where('codice', 'like', '%PRE_'.strtoupper($codice).'%')->first();
443
-        $pre_ordine = \App\Models\SaltacodaOrdine::where('codice', 'like', '%'.strtoupper($codice).'%')->first();
478
+        if($codice == '' || $codice == null) {
479
+            return view('punto_vendita.cassa._partials.pre_ordine', ['success' => false, 'error' => 'Codice pre-ordine non valido']);
480
+        }
481
+        $codice = SaltacodaOrdine::normalizzaCodice($codice);
482
+        if ($codice === '') {
483
+            return view('punto_vendita.cassa._partials.pre_ordine', ['success' => false, 'error' => 'Codice pre-ordine non valido']);
484
+        }
485
+        if (strlen($codice) < 3) {
486
+            return view('punto_vendita.cassa._partials.pre_ordine', ['success' => false, 'error' => 'Inserisci almeno 3 caratteri']);
487
+        }
444
 
488
 
445
-        // Se non trovato, prova con "PRE_" come prefisso se non già presente
446
-        if (! $pre_ordine && stripos($codice, 'PRE_') !== 0) {
447
-            $pre_ordine = \App\Models\SaltacodaOrdine::where('codice', 'like', '%PRE_'.strtoupper($codice).'%')->first();
489
+        if (! Session::has('attivita_attuale') || Session::get('attivita_attuale') === null) {
490
+            return view('punto_vendita.cassa._partials.pre_ordine', ['success' => false, 'error' => 'Attività non trovata']);
448
         }
491
         }
449
 
492
 
450
-        if (! $pre_ordine) {
451
-            return view('punto_vendita.cassa._partials.pre_ordine', ['success' => false, 'error' => 'Pre-ordine non trovato']);
493
+        $attivitaId = (int) Session::get('attivita_attuale');
494
+        $query = SaltacodaOrdine::query()->where('attivita_id', $attivitaId);
452
 
495
 
453
-            // return response()->json(['success' => false, 'message' => 'Pre-ordine non trovato']);
454
-        }
496
+        $pre_ordine = strlen($codice) >= 6
497
+            ? $query->where('codice', $codice)->first()
498
+            : $query->where('codice', 'like', $codice.'%')->first();
455
 
499
 
456
-        if (! (Session::has('attivita_attuale') && Session::get('attivita_attuale') != null && (int) Session::get('attivita_attuale') == (int) $pre_ordine->attivita_id)) {
457
-            return view('punto_vendita.cassa._partials.pre_ordine', ['success' => false, 'error' => 'Attività non trovata']);
458
-    
459
-        // return response()->json(['success' => false, 'message' => 'Pre-ordine non trovato']);
500
+        if (! $pre_ordine) {
501
+            return view('punto_vendita.cassa._partials.pre_ordine', ['success' => false, 'error' => 'Pre-ordine non trovato']);
460
         }
502
         }
461
 
503
 
462
         return view('punto_vendita.cassa._partials.pre_ordine', ['pre_ordine' => $pre_ordine]);
504
         return view('punto_vendita.cassa._partials.pre_ordine', ['pre_ordine' => $pre_ordine]);
467
     public function importa_pre_ordine(Request $request)
509
     public function importa_pre_ordine(Request $request)
468
 {
510
 {
469
     $codice = (string) $request->get('codice');
511
     $codice = (string) $request->get('codice');
512
+    if($codice == '' || $codice == null) {
513
+        return response()->json(['success' => false, 'message' => 'Codice pre-ordine non valido']);
514
+    }
515
+    $codice = SaltacodaOrdine::normalizzaCodice($codice);
470
 
516
 
471
     if (! Session::has('attivita_attuale') || Session::get('attivita_attuale') === null) {
517
     if (! Session::has('attivita_attuale') || Session::get('attivita_attuale') === null) {
472
         return response()->json(['success' => false, 'message' => 'Attività non trovata']);
518
         return response()->json(['success' => false, 'message' => 'Attività non trovata']);
492
             if (! $ordine || $ordine->stato !== Ordine::CARRELLO) {
538
             if (! $ordine || $ordine->stato !== Ordine::CARRELLO) {
493
                 return response()->json(['success' => false, 'message' => 'Ordine non valido']);
539
                 return response()->json(['success' => false, 'message' => 'Ordine non valido']);
494
             }
540
             }
541
+            AttivitaService::garantisciAttivita($ordine->attivita_id);
495
 
542
 
496
             $isPrimoImport = $pre_ordine->stato === SaltacodaOrdine::PRE_ORDINE;
543
             $isPrimoImport = $pre_ordine->stato === SaltacodaOrdine::PRE_ORDINE;
497
             $isRipristino = $pre_ordine->stato === SaltacodaOrdine::PRE_CARRELLO
544
             $isRipristino = $pre_ordine->stato === SaltacodaOrdine::PRE_CARRELLO

+ 13
- 9
app/Http/Controllers/RigaOrdineController.php Просмотреть файл

2
 
2
 
3
 namespace App\Http\Controllers;
3
 namespace App\Http\Controllers;
4
 
4
 
5
+
6
+use Illuminate\Routing\Controllers\Middleware;
5
 use Illuminate\Http\Request;
7
 use Illuminate\Http\Request;
6
 use Illuminate\Database\Eloquent\Builder;
8
 use Illuminate\Database\Eloquent\Builder;
7
 use App\Models\Dispositivo;
9
 use App\Models\Dispositivo;
23
     public static function middleware(): array
25
     public static function middleware(): array
24
     {
26
     {
25
         return [
27
         return [
26
-            new Middleware('permission:view-riga_ordine', only: ['index']),
27
-            new Middleware('permission:create-riga_ordine|edit-riga_ordine|delete-riga_ordine', only: ['store', 'update', 'destroy']),
28
+            new Middleware('permission:view-riga_ordine|view-cucina|view-asporto|view-punto_vendita', only: ['index', 'datatable', 'dettagli', 'lista_da_chiamare', 'lista_chiamate']),
29
+            new Middleware('permission:create-riga_ordine|edit-riga_ordine|delete-riga_ordine|view-cucina|view-asporto|view-punto_vendita', only: ['store', 'update', 'destroy', 'chiamata', 'ritiro']),
28
         ];
30
         ];
29
     }
31
     }
30
 
32
 
31
-    public function dettagli(Request $request){
32
-        if($request->has('riga_ordine_id')){
33
-            $riga_ordine = RigaOrdine::find($request->riga_ordine_id);
34
-            if($riga_ordine == null){ return response()->json(['success' => false, 'message' => 'Riga ordine non trovata']); }
35
-            return view('punto_vendita.cassa._partials.carrello.cmd_carrello', ['cmd' => 'dettagli', 'riga_ordine_id' => $riga_ordine->id]);
33
+    public function dettagli(Request $request)
34
+    {
35
+        if (! $request->has('riga_ordine_id')) {
36
+            return response()->json(['success' => false, 'message' => 'ID non valido']);
36
         }
37
         }
37
-        return response()->json(['success' => false, 'message' => 'ID non valido']);
38
-        
38
+
39
+        $riga_ordine = app(\App\Services\Carrello\CarrelloService::class)
40
+            ->rigaDiQuestaCassa((int) $request->riga_ordine_id);
41
+
42
+        return view('punto_vendita.cassa._partials.carrello.cmd_carrello', ['cmd' => 'dettagli', 'riga_ordine_id' => $riga_ordine->id]);
39
     }
43
     }
40
 
44
 
41
     public function lista_da_chiamare(Request $request){
45
     public function lista_da_chiamare(Request $request){

+ 2
- 2
app/Http/Controllers/RigaOrdineNotificaController.php Просмотреть файл

11
     public function salva_fcm_token(Request $request)
11
     public function salva_fcm_token(Request $request)
12
     {
12
     {
13
         $request->validate([
13
         $request->validate([
14
-            'ordine_id' => 'required|integer',
14
+            'ordine_codice' => 'required|string',
15
             'fcm_token' => 'required|string',
15
             'fcm_token' => 'required|string',
16
         ]);
16
         ]);
17
 
17
 
18
         $ordine = Ordine::query()
18
         $ordine = Ordine::query()
19
-            ->where('id', $request->input('ordine_id'))
19
+            ->where('codice', $request->input('ordine_codice'))
20
             ->where('stato', Ordine::PAGATO)
20
             ->where('stato', Ordine::PAGATO)
21
             ->first();
21
             ->first();
22
 
22
 

+ 1
- 1
app/Models/AbstractModels/AbstractOrdine.php Просмотреть файл

82
 
82
 
83
     public function punto_vendita()
83
     public function punto_vendita()
84
     {
84
     {
85
-        return $this->belongsTo('\App\Models\PuntoVendita', 'punto_vendita_id', 'id');
85
+        return $this->belongsTo('\App\Models\Dispositivo', 'punto_vendita_id', 'id');
86
     }
86
     }
87
 
87
 
88
     public function prenotazione()
88
     public function prenotazione()

+ 112
- 73
app/Services/Carrello/CarrelloService.php Просмотреть файл

5
 use App\Models\Ordine;
5
 use App\Models\Ordine;
6
 use App\Models\RigaOrdine;
6
 use App\Models\RigaOrdine;
7
 use App\Models\Piatto;
7
 use App\Models\Piatto;
8
+use App\Models\Dispositivo;
8
 use App\Models\SaltacodaOrdine;
9
 use App\Models\SaltacodaOrdine;
9
 use App\Models\VariantePiatto;
10
 use App\Models\VariantePiatto;
10
 use App\Models\RigaOrdineHasVariante;
11
 use App\Models\RigaOrdineHasVariante;
11
-use Illuminate\Database\Eloquent\ModelNotFoundException;
12
+use App\Services\Attivita\AttivitaService;
12
 
13
 
13
 class CarrelloService
14
 class CarrelloService
14
 {
15
 {
15
-    public function findCartOrFail(int $ordineId): Ordine
16
+    /**
17
+     * @return array{0: int, 1: int} [attivitaId, dispositivoId]
18
+     */
19
+    public function contestoCassa(): array
16
     {
20
     {
17
-        $ordine = Ordine::find($ordineId);
21
+        $attivitaId = (int) (session('attivita_attuale') ?: session('attivita_id'));
22
+        $dispositivoId = (int) session('dispositivo_id');
23
+        if ($attivitaId <= 0 || $dispositivoId <= 0) {
24
+            abort(404);
25
+        }
26
+
27
+        AttivitaService::garantisciAttivita($attivitaId);
28
+
29
+        $dispositivo = Dispositivo::find($dispositivoId);
30
+        if (! $dispositivo || (int) $dispositivo->attivita_id !== $attivitaId) {
31
+            abort(404);
32
+        }
33
+
34
+        return [$attivitaId, $dispositivoId];
35
+    }
18
 
36
 
19
-        if (! $ordine) {
20
-            throw new ModelNotFoundException('Ordine non trovato.');
37
+    public function carrelloDiQuestaCassa(int $ordineId): Ordine
38
+    {
39
+        [$attivitaId, $dispositivoId] = $this->contestoCassa();
40
+        $ordine = Ordine::find($ordineId);
41
+        if (
42
+            ! $ordine
43
+            || (int) $ordine->attivita_id !== $attivitaId
44
+            || (int) $ordine->dispositivo_id !== $dispositivoId
45
+            || $ordine->stato !== Ordine::CARRELLO
46
+        ) {
47
+            abort(404);
21
         }
48
         }
22
 
49
 
23
         return $ordine;
50
         return $ordine;
24
     }
51
     }
25
 
52
 
26
-    public function aumentaQuantita(int $dispositivo_id ,?int $attivita_id, ?int $ordine_id, int $piatto_id, ?int $riga_ordine_id = null): array
53
+    public function rigaDiQuestaCassa(int $rigaId): RigaOrdine
54
+    {
55
+        $riga = RigaOrdine::find($rigaId);
56
+        if (! $riga) {
57
+            abort(404);
58
+        }
59
+
60
+        $this->carrelloDiQuestaCassa((int) $riga->ordine_id);
61
+
62
+        return $riga;
63
+    }
64
+
65
+    public function findCartOrFail(int $ordineId): Ordine
66
+    {
67
+        return $this->carrelloDiQuestaCassa($ordineId);
68
+    }
69
+
70
+    public function aumentaQuantita(?int $ordine_id, int $piatto_id, ?int $riga_ordine_id = null): array
27
     {
71
     {
28
-    // Tolleranza su ordine_id stale: se non e` valido, usa/crea il carrello corrente per dispositivo+attivita.
72
+        [$attivitaId, $dispositivoId] = $this->contestoCassa();
73
+
74
+        $piatto = Piatto::where('id', $piatto_id)->where('attivita_id', $attivitaId)->first();
75
+        if (! $piatto) {
76
+            abort(404);
77
+        }
78
+
29
         $carrelloBaseQuery = Ordine::query()
79
         $carrelloBaseQuery = Ordine::query()
30
             ->where('stato', Ordine::CARRELLO)
80
             ->where('stato', Ordine::CARRELLO)
31
-            ->where('dispositivo_id', $dispositivo_id)
32
-            ->when(
33
-                $attivita_id,
34
-                fn ($q) => $q->where('attivita_id', $attivita_id)
35
-            );
81
+            ->where('dispositivo_id', $dispositivoId)
82
+            ->where('attivita_id', $attivitaId);
36
 
83
 
37
         $carrello = null;
84
         $carrello = null;
38
         if ($ordine_id) {
85
         if ($ordine_id) {
41
                 ->first();
88
                 ->first();
42
         }
89
         }
43
 
90
 
44
-        if (!$carrello) {
91
+        if (! $carrello) {
45
             $carrello = (clone $carrelloBaseQuery)->latest('id')->first();
92
             $carrello = (clone $carrelloBaseQuery)->latest('id')->first();
46
         }
93
         }
47
 
94
 
48
-        if (!$carrello) {
95
+        if (! $carrello) {
49
             $carrello = Ordine::create([
96
             $carrello = Ordine::create([
50
                 'stato' => Ordine::CARRELLO,
97
                 'stato' => Ordine::CARRELLO,
51
-                'dispositivo_id' => $dispositivo_id,
52
-                'attivita_id' => $attivita_id,
98
+                'dispositivo_id' => $dispositivoId,
99
+                'attivita_id' => $attivitaId,
53
             ]);
100
             ]);
54
         }
101
         }
55
 
102
 
56
-        if($riga_ordine_id){
57
-            $riga = RigaOrdine::findOrFail($riga_ordine_id);
58
-        }else{
103
+        if ($riga_ordine_id) {
104
+            $riga = RigaOrdine::where('id', $riga_ordine_id)
105
+                ->where('ordine_id', $carrello->id)
106
+                ->first();
107
+            if (! $riga) {
108
+                abort(404);
109
+            }
110
+        } else {
59
             $riga = RigaOrdine::where('ordine_id', $carrello->id)->where('piatto_id', $piatto_id)->whereDoesntHave('has_variante')->oldest('id')->first();
111
             $riga = RigaOrdine::where('ordine_id', $carrello->id)->where('piatto_id', $piatto_id)->whereDoesntHave('has_variante')->oldest('id')->first();
60
         }
112
         }
61
         // else{
113
         // else{
97
 
149
 
98
     public function diminuisciQuantita(int $ordine_id, int $piatto_id, int $riga_ordine_id): array
150
     public function diminuisciQuantita(int $ordine_id, int $piatto_id, int $riga_ordine_id): array
99
     {
151
     {
100
-        $carrello = Ordine::findOrFail($ordine_id);
101
-        // $riga = RigaOrdine::where('ordine_id', $carrello->id)->where('piatto_id', $piatto_id)->first();
102
-        $riga = RigaOrdine::findOrFail($riga_ordine_id);
103
-        if($riga && $riga->id == $riga_ordine_id){
104
-            // $piatto = Piatto::findOrFail($piatto_id);
105
-            $piatto = $riga->piatto;
106
-            $riga->quantita -= 1;
152
+        $carrello = $this->carrelloDiQuestaCassa($ordine_id);
153
+        $riga = RigaOrdine::where('id', $riga_ordine_id)->where('ordine_id', $carrello->id)->first();
154
+        if (! $riga) {
155
+            abort(404);
156
+        }
107
 
157
 
108
-            if($riga->quantita == 0){
109
-                $riga->delete();
110
-                return [
111
-                    'ordine' => $carrello,
112
-                    'riga' => null,
113
-                ];
114
-            };
158
+        $riga->quantita -= 1;
115
 
159
 
116
-            $riga->prezzo = $this->calcolaPrezzoRiga($riga);
117
-            $riga->save();   
160
+        if ($riga->quantita == 0) {
161
+            $riga->delete();
162
+
163
+            return [
164
+                'ordine' => $carrello,
165
+                'riga' => null,
166
+            ];
118
         }
167
         }
168
+
169
+        $riga->prezzo = $this->calcolaPrezzoRiga($riga);
170
+        $riga->save();
171
+
119
         return [
172
         return [
120
             'ordine' => $carrello,
173
             'ordine' => $carrello,
121
             'riga' => $riga,
174
             'riga' => $riga,
124
 
177
 
125
     public function eliminaRiga(int $rigaOrdineId, bool $elimina = false): void
178
     public function eliminaRiga(int $rigaOrdineId, bool $elimina = false): void
126
     {
179
     {
127
-        $riga = RigaOrdine::find($rigaOrdineId);
128
-        if($riga !== null && $elimina){
129
-        $riga->delete();
130
-        };
180
+        $riga = $this->rigaDiQuestaCassa($rigaOrdineId);
181
+        if ($elimina) {
182
+            $riga->delete();
183
+        }
131
     }
184
     }
132
 
185
 
133
     public function azzeraCarrello(int $ordine_id): array
186
     public function azzeraCarrello(int $ordine_id): array
134
     {
187
     {
135
-        $ordine = Ordine::find($ordine_id);
136
-
137
-        if($ordine == null){
138
-            return [
139
-                'success' => false,
140
-                'message' => 'Ordine non trovato',
141
-                'data' => null,  
142
-            ];
143
-        }
188
+        $ordine = $this->carrelloDiQuestaCassa($ordine_id);
144
 
189
 
145
         $preOrdineId = data_get($ordine->info, 'pre_ordine_id');
190
         $preOrdineId = data_get($ordine->info, 'pre_ordine_id');
146
         $preOrdineCodice = data_get($ordine->info, 'pre_ordine_codice');
191
         $preOrdineCodice = data_get($ordine->info, 'pre_ordine_codice');
187
 
232
 
188
     public function aggiornaNota(int $rigaOrdineId, string $note = null): RigaOrdine
233
     public function aggiornaNota(int $rigaOrdineId, string $note = null): RigaOrdine
189
     {
234
     {
190
-        $riga = RigaOrdine::findOrFail($rigaOrdineId);
191
-        if($riga == null){
192
-            throw new ModelNotFoundException('Riga ordine non trovata.');
193
-        };
194
-
235
+        $riga = $this->rigaDiQuestaCassa($rigaOrdineId);
195
         $riga->note = $note;
236
         $riga->note = $note;
196
         $riga->save();
237
         $riga->save();
238
+
197
         return $riga;
239
         return $riga;
198
     }
240
     }
199
 
241
 
200
     public function aggiungiVarianteSingoloPiatto(int $piattoId, int $rigaOrdineId, array $varianteIds, string $nota = null): array
242
     public function aggiungiVarianteSingoloPiatto(int $piattoId, int $rigaOrdineId, array $varianteIds, string $nota = null): array
201
     {
243
     {
202
         $varianteIds = array_values(array_unique(array_map('intval', array_filter($varianteIds))));
244
         $varianteIds = array_values(array_unique(array_map('intval', array_filter($varianteIds))));
203
-    
245
+
204
         if (empty($varianteIds)) {
246
         if (empty($varianteIds)) {
205
             return [
247
             return [
206
                 'success' => false,
248
                 'success' => false,
208
                 'data' => null,
250
                 'data' => null,
209
             ];
251
             ];
210
         }
252
         }
211
-    
212
-        $riga = RigaOrdine::findOrFail($rigaOrdineId);
213
-        $piatto = Piatto::findOrFail($piattoId);
253
+
254
+        $riga = $this->rigaDiQuestaCassa($rigaOrdineId);
255
+        [$attivitaId] = $this->contestoCassa();
256
+        $piatto = Piatto::where('id', $piattoId)->where('attivita_id', $attivitaId)->first();
257
+        if (! $piatto) {
258
+            abort(404);
259
+        }
214
         $targetRiga = $riga;
260
         $targetRiga = $riga;
215
     
261
     
216
         // qty > 1: splitta una volta, poi tutte le varianti vanno sulla nuova riga
262
         // qty > 1: splitta una volta, poi tutte le varianti vanno sulla nuova riga
233
         $aggiunte = 0;
279
         $aggiunte = 0;
234
     
280
     
235
         foreach ($varianteIds as $varianteId) {
281
         foreach ($varianteIds as $varianteId) {
236
-            VariantePiatto::findOrFail($varianteId);
282
+            $variante = VariantePiatto::where('id', $varianteId)->where('attivita_id', $attivitaId)->first();
283
+            if (! $variante) {
284
+                abort(404);
285
+            }
237
     
286
     
238
             $giaPresente = RigaOrdineHasVariante::where('riga_ordine_id', $targetRiga->id)
287
             $giaPresente = RigaOrdineHasVariante::where('riga_ordine_id', $targetRiga->id)
239
                 ->where('variante_id', $varianteId)
288
                 ->where('variante_id', $varianteId)
273
 
322
 
274
     public function eliminaVariante(int $rigaOrdineId, int $varianteId): array
323
     public function eliminaVariante(int $rigaOrdineId, int $varianteId): array
275
     {
324
     {
276
-        $riga = RigaOrdine::findOrFail($rigaOrdineId);
277
-        if($riga == null){
278
-            return [
279
-                'success' => false,
280
-                'message' => 'Riga ordine non trovata.',
281
-                'data' => null,
282
-            ];
283
-        }
284
-        $variante = VariantePiatto::findOrFail($varianteId);
285
-        if($variante == null){
286
-            return [
287
-                'success' => false,
288
-                'message' => 'Variante non trovata.',
289
-                'data' => null,
290
-            ];
325
+        $riga = $this->rigaDiQuestaCassa($rigaOrdineId);
326
+        [$attivitaId] = $this->contestoCassa();
327
+        $variante = VariantePiatto::where('id', $varianteId)->where('attivita_id', $attivitaId)->first();
328
+        if (! $variante) {
329
+            abort(404);
291
         }
330
         }
292
         $pivotVariante = RigaOrdineHasVariante::where('riga_ordine_id', $riga->id)->where('variante_id', $varianteId)->first();
331
         $pivotVariante = RigaOrdineHasVariante::where('riga_ordine_id', $riga->id)->where('variante_id', $varianteId)->first();
293
         if($pivotVariante == null){
332
         if($pivotVariante == null){

+ 4
- 4
resources/js/ordine-notifica.js Просмотреть файл

82
 
82
 
83
     const fcmToken = await chiediTokenFcm();
83
     const fcmToken = await chiediTokenFcm();
84
 
84
 
85
-    const ordineId = btn.dataset.ordineId;
86
-    if (!ordineId) {
87
-      throw new Error('ID ordine non trovato nella pagina');
85
+    const ordineCodice = btn.dataset.ordineCodice;
86
+    if (!ordineCodice) {
87
+      throw new Error('Codice ordine non trovato nella pagina');
88
     }
88
     }
89
 
89
 
90
     const body = new FormData();
90
     const body = new FormData();
91
     body.append('fcm_token', fcmToken);
91
     body.append('fcm_token', fcmToken);
92
-    body.append('ordine_id', ordineId);
92
+    body.append('ordine_codice', ordineCodice);
93
 
93
 
94
     const res = await fetch(window.subscribeUrl, {
94
     const res = await fetch(window.subscribeUrl, {
95
       method: 'POST',
95
       method: 'POST',

+ 1
- 0
resources/views/operatore/show.blade.php Просмотреть файл

103
         <form action="{{ route('operatore.update.password', $operatore->id) }}" method="post">
103
         <form action="{{ route('operatore.update.password', $operatore->id) }}" method="post">
104
           @csrf
104
           @csrf
105
           @method('POST')
105
           @method('POST')
106
+          <input type="hidden" name="operatore_id" value="{{ $operatore->id }}">
106
           <div class="mb-3">
107
           <div class="mb-3">
107
             <label for="password" class="form-label">Password</label>
108
             <label for="password" class="form-label">Password</label>
108
             <input type="password" class="form-control" id="password" name="password">
109
             <input type="password" class="form-control" id="password" name="password">

+ 373
- 309
resources/views/ordine/show.blade.php Просмотреть файл

1
-<?php
2
-use App\Models\Role;
3
-use Illuminate\Support\Facades\Auth;
4
-?>
5
 @php
1
 @php
6
-$configData = Helper::appClasses();
7
-@endphp
2
+use App\Models\Ordine;
3
+use App\Models\RigaOrdine;
4
+use Illuminate\Support\Str;
8
 
5
 
9
-@extends('layouts/layoutMaster')
6
+$tipoMeta = $ordine->tipo ? (Ordine::getTipi()->get($ordine->tipo) ?? []) : [];
7
+$totale = $ordine->prezzo !== null
8
+    ? (float) $ordine->prezzo
9
+    : (float) $ordine->righe_ordine->sum('prezzo');
10
+$nRighe = $ordine->righe_ordine->count();
11
+$nPezzi = (int) $ordine->righe_ordine->sum('quantita');
12
+$datiCassa = is_array($ordine->info) ? $ordine->info : [];
13
+$infoLabels = [
14
+    'cliente' => 'Cliente',
15
+    'tavolo' => 'Tavolo',
16
+    'coperti' => 'Coperti',
17
+];
18
+$infoVisibili = collect($datiCassa)
19
+    ->reject(fn ($valore) => $valore === null || $valore === '' || $valore === [])
20
+    ->all();
21
+$cliente = $datiCassa['cliente'] ?? null;
22
+$tavolo = $datiCassa['tavolo'] ?? null;
23
+$coperti = $datiCassa['coperti'] ?? null;
24
+$isCarrello = $ordine->stato === Ordine::CARRELLO;
10
 
25
 
11
-@section('title', 'Ordini')
26
+$iconePagamento = [
27
+    'carta_di_credito' => 'bx-credit-card',
28
+    'carta_di_debito' => 'bx-credit-card',
29
+    'bonifico' => 'bx-transfer',
30
+    'paypal' => 'bx-paypal',
31
+    'stripe' => 'bx-credit-card',
32
+    'contanti' => 'bx-money',
33
+    'credito' => 'bx-wallet',
34
+    'apple_pay' => 'bx-mobile',
35
+    'google_pay' => 'bx-mobile',
36
+    'cupon' => 'bx-purchase-tag',
37
+    'segresta_wallet' => 'bx-wallet',
38
+    'pos' => 'bx-credit-card',
39
+    'staff' => 'bx-id-card',
40
+];
41
+@endphp
12
 
42
 
13
-@section('vendor-style')
14
-@vite([
15
-'resources/assets/vendor/libs/datatables-bs5/datatables.bootstrap5.scss',
16
-'resources/assets/vendor/libs/datatables-responsive-bs5/responsive.bootstrap5.scss',
17
-'resources/assets/vendor/libs/datatables-buttons-bs5/buttons.bootstrap5.scss',
18
-'resources/assets/vendor/libs/flatpickr/flatpickr.scss',
19
-'resources/assets/vendor/libs/@form-validation/form-validation.scss'
20
-])
21
-@endsection
43
+@extends('layouts/layoutMaster')
22
 
44
 
23
-<!-- Vendor Scripts -->
24
-@section('vendor-script')
25
-@vite([
26
-'resources/assets/vendor/libs/moment/moment.js',
27
-'resources/assets/vendor/libs/flatpickr/flatpickr.js',
28
-'resources/assets/vendor/libs/@form-validation/popular.js',
29
-'resources/assets/vendor/libs/@form-validation/bootstrap5.js',
30
-'resources/assets/vendor/libs/@form-validation/auto-focus.js',
31
-'resources/assets/vendor/libs/@form-validation/popular.js',
32
-'resources/assets/vendor/libs/@form-validation/bootstrap5.js',
33
-'resources/assets/vendor/libs/@form-validation/auto-focus.js',
34
-'resources/assets/vendor/libs/datatables-bs5/datatables-bootstrap5.js'
35
-])
36
-@endsection
45
+@section('title', 'Ordine #'.$ordine->id)
37
 
46
 
38
 @section('pageTitle')
47
 @section('pageTitle')
39
 <div class="d-flex flex-column">
48
 <div class="d-flex flex-column">
40
-  <h4 class="mb-1"> 
41
-    <i class="bx bx-receipt"></i> Ordine #{{ $ordine->id }}
42
-    <small class="text-muted">{{ view('prenotazione._partials.stato-prenotazione', ['stato' => $ordine->stato]) }}</small>
43
-</h4>
49
+  <h4 class="mb-0 text-sm-small">
50
+    <i class="bx bx-receipt d-none d-md-inline-flex"></i>
51
+    Dettaglio ordine
52
+  </h4>
53
+  <nav aria-label="breadcrumb" style="font-size: smaller;" class="d-none d-md-block">
54
+    <ol class="breadcrumb breadcrumb-custom-icon mb-0">
55
+      <li class="breadcrumb-item">
56
+        <a href="{{ route('ordine.index') }}">Ordini</a>
57
+        <i class="breadcrumb-icon icon-base bx bx-chevron-right align-middle"></i>
58
+      </li>
59
+      <li class="breadcrumb-item active text-primary">#{{ $ordine->id }}</li>
60
+    </ol>
61
+  </nav>
44
 </div>
62
 </div>
45
 @endsection
63
 @endsection
46
 
64
 
47
 @section('content')
65
 @section('content')
66
+@include('_partials.status')
67
+
48
 <style>
68
 <style>
49
-  div.upload button:first-child{
50
-    display: none !important;
69
+  .or-show-hero {
70
+    border: 1px solid rgba(67, 89, 113, .12);
71
+    border-radius: 1rem;
72
+    overflow: hidden;
73
+    background: var(--bs-paper-bg, #fff);
74
+  }
75
+  .or-show-hero__main {
76
+    display: flex;
77
+    flex-wrap: wrap;
78
+    align-items: center;
79
+    justify-content: space-between;
80
+    gap: 1.25rem;
81
+    padding: 1.35rem 1.5rem;
82
+  }
83
+  .or-show-hero__amount {
84
+    font-size: clamp(1.75rem, 4vw, 2.35rem);
85
+    font-weight: 700;
86
+    line-height: 1.1;
87
+    letter-spacing: -0.02em;
88
+    color: var(--bs-heading-color);
89
+  }
90
+  .or-show-hero__meta {
91
+    display: flex;
92
+    flex-wrap: wrap;
93
+    align-items: center;
94
+    gap: .5rem;
95
+  }
96
+  .or-show-hero__title {
97
+    font-size: 1.15rem;
98
+    font-weight: 600;
99
+    margin-bottom: .35rem;
100
+  }
101
+  .or-show-hero__sub {
102
+    color: var(--bs-secondary-color);
103
+    font-size: .875rem;
104
+  }
105
+  .or-show-section-title {
106
+    font-size: .8rem;
107
+    font-weight: 600;
108
+    text-transform: uppercase;
109
+    letter-spacing: .04em;
110
+    color: var(--bs-secondary-color);
111
+    margin-bottom: .75rem;
112
+  }
113
+  .or-show-dl dt {
114
+    color: var(--bs-secondary-color);
115
+    font-weight: 500;
116
+    font-size: .8125rem;
117
+  }
118
+  .or-show-dl dd {
119
+    font-size: .9375rem;
120
+    margin-bottom: .65rem;
121
+  }
122
+  .or-show-link-card {
123
+    display: flex;
124
+    align-items: center;
125
+    gap: .85rem;
126
+    padding: .85rem 1rem;
127
+    border: 1px solid rgba(67, 89, 113, .12);
128
+    border-radius: .75rem;
129
+    background: var(--bs-paper-bg, #fff);
130
+    transition: border-color .15s ease, box-shadow .15s ease;
131
+  }
132
+  .or-show-link-card:hover {
133
+    border-color: rgba(var(--bs-primary-rgb), .35);
134
+    box-shadow: 0 .125rem .5rem rgba(67, 89, 113, .08);
135
+  }
136
+  .or-show-link-card--empty {
137
+    opacity: .72;
138
+    background: rgba(67, 89, 113, .03);
139
+  }
140
+  .or-show-link-card__icon {
141
+    width: 2.5rem;
142
+    height: 2.5rem;
143
+    border-radius: .65rem;
144
+    display: flex;
145
+    align-items: center;
146
+    justify-content: center;
147
+    flex-shrink: 0;
148
+    background: rgba(var(--bs-primary-rgb), .1);
149
+    color: var(--bs-primary);
150
+    font-size: 1.25rem;
151
+  }
152
+  .or-show-link-card--empty .or-show-link-card__icon {
153
+    background: rgba(67, 89, 113, .08);
154
+    color: var(--bs-secondary-color);
155
+  }
156
+  .or-show-link-card__body { flex: 1; min-width: 0; }
157
+  .or-show-link-card__label {
158
+    font-size: .75rem;
159
+    color: var(--bs-secondary-color);
160
+    margin-bottom: .1rem;
161
+  }
162
+  .or-show-link-card__title {
163
+    font-weight: 600;
164
+    font-size: .9375rem;
165
+    line-height: 1.3;
166
+  }
167
+  .or-show-link-card__subtitle {
168
+    font-size: .8125rem;
169
+    color: var(--bs-secondary-color);
170
+    margin-top: .15rem;
171
+  }
172
+  .or-show-qty {
173
+    min-width: 2.25rem;
174
+    height: 2.25rem;
175
+    border-radius: .65rem;
176
+    display: inline-flex;
177
+    align-items: center;
178
+    justify-content: center;
179
+    font-weight: 700;
180
+    background: rgba(var(--bs-primary-rgb), .1);
181
+    color: var(--bs-primary);
182
+  }
183
+  .or-show-line + .or-show-line {
184
+    border-top: 1px solid rgba(67, 89, 113, .1);
51
   }
185
   }
52
-
53
-.bx-chef-hat{
54
-  --svg: url("data:image/svg+xml,%3csvg width='24' height='24' fill='currentColor' viewBox='0 0 24 24' transform='' xmlns='http://www.w3.org/2000/svg'%3e%3c!--Boxicons v3.0.8 https://boxicons.com %7c License https://docs.boxicons.com/free--%3e%3cpath d='M17.13 5.54C16.33 3.42 14.32 2 12 2S7.67 3.42 6.87 5.54A5.506 5.506 0 0 0 2 11c0 2.07 1.18 3.95 3 4.88V18c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-2.12c1.82-.93 3-2.81 3-4.88 0-2.82-2.13-5.15-4.87-5.46m.53 8.75c-.4.14-.67.52-.67.94v1.78H7v-1.78c0-.42-.27-.8-.67-.94-1.4-.5-2.33-1.82-2.33-3.28 0-1.93 1.57-3.5 3.42-3.5.04 0 .14.01.18.02.49 0 .9-.31 1-.78.36-1.61 1.76-2.73 3.41-2.73s3.05 1.12 3.41 2.73c.1.47.51.81 1 .78.06 0 .12 0 .09-.01 1.93 0 3.5 1.57 3.5 3.5 0 1.47-.94 2.79-2.33 3.28ZM5 20h14v2H5z'%3e%3c/path%3e%3c/svg%3e");
55
-}
56
-
57
-.report-list-item-li:hover{
58
-    transition: box-shadow 0.3s;
59
-    box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);
60
-    cursor: pointer;
61
-}
62
-
63
-
64
 </style>
186
 </style>
65
 
187
 
66
-@include('_partials.status')
188
+<div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-3">
189
+  <a href="{{ route('ordine.index') }}" class="btn btn-label-secondary btn-sm">
190
+    <i class="bx bx-arrow-back me-1"></i> Torna agli ordini
191
+  </a>
192
+  <span class="text-muted small">ID ordine <strong>#{{ $ordine->id }}</strong></span>
193
+</div>
67
 
194
 
68
-@include('ordine._partials.card_statistiche')
195
+<div class="or-show-hero mb-4">
196
+  <div class="or-show-hero__main">
197
+    <div class="flex-grow-1 min-w-0">
198
+      <div class="or-show-hero__meta mb-2">
199
+        @include('prenotazione._partials.stato-prenotazione', ['stato' => $ordine->stato])
200
+        @if(!empty($tipoMeta['label']))
201
+          <span class="badge bg-label-info">{{ $tipoMeta['label'] }}</span>
202
+        @endif
203
+        @if($ordine->dispositivo)
204
+          <span class="badge bg-label-secondary">{{ $ordine->dispositivo->nome }}</span>
205
+        @endif
206
+        @if($ordine->codice && strlen((string) $ordine->codice) <= 12)
207
+          <span class="badge bg-label-primary">Codice {{ $ordine->codice }}</span>
208
+        @endif
209
+      </div>
69
 
210
 
70
-<div class="row justify-content-center">
211
+      <div class="or-show-hero__title">
212
+        Ordine #{{ $ordine->id }}
213
+        @if(filled($cliente))
214
+          · {{ $cliente }}
215
+        @endif
216
+      </div>
71
 
217
 
72
-  <!-- Card 1: Informazioni Ordine -->
73
-  <div class="col-12 col-md-4 col-xl-3 mb-4 mt-2">
74
-    <div class="card h-100">
75
-      <div class="card-header d-flex align-items-center justify-content-between">
76
-        <h5 class="card-title m-0 me-2">Informazioni ordine</h5>
218
+      <div class="or-show-hero__sub">
219
+        <i class="bx bx-time-five me-1"></i>
220
+        {{ $ordine->created_at?->format('d/m/Y') }} alle {{ $ordine->created_at?->format('H:i') }}
221
+        @if(filled($tavolo))
222
+          · Tavolo {{ $tavolo }}
223
+        @endif
224
+        @if(filled($coperti) && (int) $coperti > 0)
225
+          · {{ $coperti }} coperti
226
+        @endif
227
+        · {{ $nPezzi }} {{ $nPezzi === 1 ? 'articolo' : 'articoli' }}
77
       </div>
228
       </div>
78
-      <div class="card-body">
79
-      <div class="mb-3">
80
-          <p><strong>Dispositivo:</strong> {{ $ordine->dispositivo->nome ?? '-' }}</p>
81
-        </div>
82
-      <div class="mb-3">
83
-          <p><strong>Data creazione:</strong> {{ $ordine->created_at->format('d/m/Y H:i') }}</p>
84
-        </div>
85
-        <div class="mb-3">
86
-          <p><strong>Stato:</strong> 
87
-            {!! view('prenotazione._partials.stato-prenotazione', ['stato' => $ordine->stato]) !!}
88
-          </p>
89
-        </div>
90
-        <div class="mb-3">
91
-          <p><strong>Tipo:</strong> {{ $ordine->tipo ?? '-' }}</p>
92
-        </div>
93
-        <div class="mb-3">
94
-          <p><strong>Riferimento:</strong> {{ $ordine->riferimento ?? '-' }}</p>
95
-        </div>
96
-        <div class="mb-3">
97
-          <p><strong>Note:</strong> {{ $ordine->note ?? '-' }}</p>
98
-        </div>
99
-        @if($ordine->info)
100
-        <div class="mb-3">
101
-          <p><strong>Info extra:</strong>
102
-            @php
103
-              $infoArr = is_array($ordine->info) ? $ordine->info : (json_decode($ordine->info, true) ?? []);
104
-            @endphp
105
-            @if(!empty($infoArr))
106
-                @foreach($infoArr as $key => $value)
107
-                  <span class="d-block"><strong>{{ ucfirst($key) }}:</strong> {{ $value }}</span>
108
-                @endforeach
109
-            @endif
110
-          </p>
111
-        </div>
229
+    </div>
230
+
231
+    <div class="text-end">
232
+      <div class="or-show-hero__amount">€ {{ number_format($totale, 2, ',', '.') }}</div>
233
+      <div class="text-muted small mt-1">
234
+        @if($isCarrello)
235
+          Totale carrello
236
+        @else
237
+          Totale ordine
112
         @endif
238
         @endif
113
       </div>
239
       </div>
114
     </div>
240
     </div>
115
   </div>
241
   </div>
242
+</div>
116
 
243
 
117
-  <!-- Card 2: Piatti -->
118
-  <div class="col-12 col-md-6 col-xl-5 mb-4 mt-2">
244
+<div class="row g-4">
245
+  <div class="col-12 col-lg-8">
119
     <div class="card h-100">
246
     <div class="card h-100">
120
-      <div class="card-header d-flex align-items-center justify-content-between">
121
-        <h5 class="card-title m-0 me-2">Piatti</h5>
122
-        <div class="dropdown">
123
-          <button class="btn text-muted p-0" type="button" id="transactionID" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
124
-            <i class="bx bx-dots-vertical-rounded bx-lg"></i>
125
-          </button>
126
-          <div class="dropdown-menu dropdown-menu-end" aria-labelledby="transactionID">
127
-            <a class="dropdown-item" href="javascript:void(0);">Last 28 Days</a>
128
-            <a class="dropdown-item" href="javascript:void(0);">Last Month</a>
129
-            <a class="dropdown-item" href="javascript:void(0);">Last Year</a>
130
-          </div>
247
+      <div class="card-body">
248
+        <div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-3">
249
+          <div class="or-show-section-title mb-0">Articoli</div>
250
+          <span class="badge bg-label-secondary">{{ $nRighe }} {{ $nRighe === 1 ? 'riga' : 'righe' }}</span>
131
         </div>
251
         </div>
132
-      </div>
133
-      <div class="card-body pt-4">
134
-        <ul class="p-0 m-0">
135
-        @foreach($ordine->righe_ordine as $riga)  
136
-        <li class="d-flex align-items-center mb-6">
137
-            <div class="d-flex align-items-center gap-2 justify-content-center w-px-50 fs-4">
138
-                <span class="fw-normal mb-0">{{ $riga->quantita }} x</span>
139
-            </div>
140
 
252
 
141
-            <div class="avatar flex-shrink-0 me-3">
142
-                @if($riga->piatto->immagine)
143
-                  <img src="{{asset('assets/img/piatti/'.$riga->piatto->immagine)}}" alt="User" class="rounded">
144
-                @else
145
-                  <span class="avatar-icon bx bx-dish rounded" style="font-size:2rem; color: #ccc; display: flex; align-items: center; justify-content: center; width: 40px; height: 40px; background: #f0f0f0;"></span>
146
-                @endif
147
-            </div>
148
-            <div class="d-flex w-100 flex-wrap align-items-center justify-content-between gap-2">
149
-              <div class="me-2">
150
-                <h6 class="mb-0">{{ $riga->piatto->nome }}</h6>
151
-                <small class="d-block mb-2">{{ \Illuminate\Support\Str::limit($riga->piatto->descrizione, 50) }}</small>
152
-                @if($riga->note)
153
-                  <small class="d-block text-muted"><i class="bx bx-chat me-2 text-warning"></i> {{ $riga->note }}</small>
154
-                @endif
155
-                @if($riga->piatto->elencoAllergeni->isNotEmpty())
156
-                  <small class="d-block text-muted"><i class="bx bx-info-circle me-2 text-warning"></i> Allergeni: {{ $riga->piatto->elencoAllergeni->implode(', ') }}</small>
157
-                @endif
158
-              </div>
159
-              <div class="user-progress d-flex align-items-center gap-2">
160
-                 <span class="text-muted"> € {{ number_format($riga->piatto->prezzo, 2, ',', '.') }}</span>
253
+        @forelse($ordine->righe_ordine as $riga)
254
+          @php
255
+            $piatto = $riga->piatto;
256
+            $varianti = ($riga->has_variante ?? collect())->filter(fn ($v) => $v->variante_id !== null);
257
+            $allergeni = $piatto?->elencoAllergeni?->pluck('nome')->filter()->implode(', ');
258
+            $statoRiga = RigaOrdine::getStati()->get($riga->stato);
259
+          @endphp
260
+          <div class="or-show-line py-3 d-flex align-items-start gap-3">
261
+            <div class="or-show-qty">{{ (int) $riga->quantita }}</div>
262
+            <div class="flex-grow-1 min-w-0">
263
+              <div class="d-flex flex-wrap justify-content-between gap-2">
264
+                <div class="fw-semibold">{{ $piatto->nome ?? ('Piatto #'.$riga->piatto_id) }}</div>
265
+                <div class="fw-semibold text-nowrap">€ {{ number_format((float) $riga->prezzo, 2, ',', '.') }}</div>
161
               </div>
266
               </div>
267
+
268
+              @if($piatto?->cucina?->nome)
269
+                <div class="small text-muted">{{ $piatto->cucina->nome }}</div>
270
+              @endif
271
+
272
+              @foreach($varianti as $variante)
273
+                <div class="small text-muted">
274
+                  <i class="bx bx-plus-circle me-1"></i>
275
+                  {{ $variante->variante_piatto->label ?? 'Variante' }}
276
+                  @if(filled($variante->nota))
277
+                    <em>({{ $variante->nota }})</em>
278
+                  @endif
279
+                </div>
280
+              @endforeach
281
+
282
+              @if(filled($riga->note))
283
+                <div class="small text-warning">
284
+                  <i class="bx bx-chat me-1"></i>{{ $riga->note }}
285
+                </div>
286
+              @endif
287
+
288
+              @if(filled($allergeni))
289
+                <div class="small text-muted">
290
+                  <i class="bx bx-info-circle me-1"></i>Allergeni: {{ $allergeni }}
291
+                </div>
292
+              @endif
293
+
294
+              @if(!empty($statoRiga['label']) && $riga->stato && $riga->stato !== RigaOrdine::ORDINATO)
295
+                <span class="badge bg-label-secondary mt-1">{{ $statoRiga['label'] }}</span>
296
+              @endif
162
             </div>
297
             </div>
163
-          </li>
164
-        @endforeach
165
-        </ul>
298
+          </div>
299
+        @empty
300
+          <p class="text-muted mb-0">Nessun articolo in questo ordine.</p>
301
+        @endforelse
166
       </div>
302
       </div>
167
     </div>
303
     </div>
168
   </div>
304
   </div>
169
 
305
 
170
-  <!-- Card 3: Riepilogo Prezzo ed Entità Collegate -->
171
-  <div class="col-12 col-md-6 col-xl-4 mb-4 mt-2">
172
-    <div class="card h-100">
173
-      <div class="card-header d-flex align-items-center justify-content-between">
174
-        <h5 class="card-title m-0 me-2">Riepilogo Ordine</h5>
306
+  <div class="col-12 col-lg-4">
307
+    <div class="card mb-4">
308
+      <div class="card-body">
309
+        <div class="or-show-section-title">Informazioni</div>
310
+        <dl class="row or-show-dl mb-0">
311
+          <dt class="col-5">Cassa</dt>
312
+          <dd class="col-7 fw-medium">{{ $ordine->dispositivo?->nome ?? '—' }}</dd>
313
+
314
+          <dt class="col-5">Creato</dt>
315
+          <dd class="col-7">{{ $ordine->created_at?->format('d/m/Y H:i') ?? '—' }}</dd>
316
+
317
+          @if($ordine->updated_at && $ordine->updated_at->ne($ordine->created_at))
318
+            <dt class="col-5">Aggiornato</dt>
319
+            <dd class="col-7">{{ $ordine->updated_at->format('d/m/Y H:i') }}</dd>
320
+          @endif
321
+
322
+          @if(!empty($tipoMeta['label']))
323
+            <dt class="col-5">Tipo</dt>
324
+            <dd class="col-7">{{ $tipoMeta['label'] }}</dd>
325
+          @endif
326
+
327
+          @if(filled($ordine->riferimento))
328
+            <dt class="col-5">Riferimento</dt>
329
+            <dd class="col-7">{{ $ordine->riferimento }}</dd>
330
+          @endif
331
+
332
+          @if(filled($ordine->codice))
333
+            <dt class="col-5">Codice</dt>
334
+            <dd class="col-7 text-break">{{ $ordine->codice }}</dd>
335
+          @endif
336
+        </dl>
337
+
338
+        @if(filled($ordine->note))
339
+          <div class="or-show-section-title mt-3">Note</div>
340
+          <p class="mb-0">{{ $ordine->note }}</p>
341
+        @endif
342
+
343
+        @if($infoVisibili !== [])
344
+          <div class="or-show-section-title mt-3">Dati raccolti in cassa</div>
345
+          <dl class="row or-show-dl mb-0">
346
+            @foreach($infoVisibili as $chiave => $valore)
347
+              <dt class="col-5">{{ $infoLabels[$chiave] ?? Str::headline((string) $chiave) }}</dt>
348
+              <dd class="col-7">
349
+                @if(is_array($valore) || is_object($valore))
350
+                  <code>{{ json_encode($valore, JSON_UNESCAPED_UNICODE) }}</code>
351
+                @elseif(in_array($chiave, ['asporto'], true) || is_bool($valore))
352
+                  {{ filter_var($valore, FILTER_VALIDATE_BOOLEAN) ? 'Sì' : 'No' }}
353
+                @else
354
+                  {{ $valore }}
355
+                @endif
356
+              </dd>
357
+            @endforeach
358
+          </dl>
359
+        @endif
175
       </div>
360
       </div>
361
+    </div>
362
+
363
+    <div class="card">
176
       <div class="card-body">
364
       <div class="card-body">
177
-        <div class="mb-4">
178
-          <h6 class="fw-bold mb-2">Totale Ordine</h6>
179
-          <div class="fs-3 fw-bold text-success">
180
-            @if($ordine->prezzo != null)
181
-            € {{ number_format($ordine->prezzo, 2, ',', '.') }} 
182
-            @else
183
-            € {{ number_format($ordine->righe_ordine->sum('prezzo'), 2, ',', '.') }} <small class="text-muted text-grey">(carrello aperto)</small>
184
-            @endif
185
-          </div>
186
-        </div>
187
-        <div class="mb-3">
188
-          <h6 class="fw-bold mb-2">Prenotazione</h6>
365
+        <div class="or-show-section-title">Collegamenti</div>
366
+        <div class="d-flex flex-column gap-3">
189
           @if($ordine->prenotazione)
367
           @if($ordine->prenotazione)
190
-            {!! view('prenotazione._partials.btn-link', ['prenotazione' => $ordine->prenotazione]) !!}
368
+            <a href="{{ route('prenotazione.show', ['prenotazione_id' => $ordine->prenotazione_id]) }}" class="or-show-link-card text-body text-decoration-none">
369
+              <div class="or-show-link-card__icon"><i class="bx bx-calendar-check"></i></div>
370
+              <div class="or-show-link-card__body">
371
+                <div class="or-show-link-card__label">Prenotazione</div>
372
+                <div class="or-show-link-card__title">{{ $ordine->prenotazione->label() }}</div>
373
+                @if(filled($ordine->prenotazione->email))
374
+                  <div class="or-show-link-card__subtitle">{{ $ordine->prenotazione->email }}</div>
375
+                @endif
376
+              </div>
377
+              <i class="bx bx-chevron-right text-muted"></i>
378
+            </a>
191
           @else
379
           @else
192
-            <span class="badge bg-label-secondary">Nessuna prenotazione associata</span>
380
+            <div class="or-show-link-card or-show-link-card--empty">
381
+              <div class="or-show-link-card__icon"><i class="bx bx-calendar-check"></i></div>
382
+              <div class="or-show-link-card__body">
383
+                <div class="or-show-link-card__label">Prenotazione</div>
384
+                <div class="or-show-link-card__title text-muted">Non collegata</div>
385
+              </div>
386
+            </div>
193
           @endif
387
           @endif
194
-        </div>
195
-        @if($ordine->pagamenti->count() > 0)
196
-        <div class="mb-3">
197
-          <h6 class="fw-bold mb-2">Pagamenti</h6>
198
-          <ul class="list-unstyled mb-0">
199
-            @foreach($ordine->pagamenti as $pagamento)
200
-              <!-- <li>
201
-                <span>
202
-                  <i class="bx bx-credit-card me-1"></i>
203
-                  {{ $pagamento->metodo_pagamento->nome ?? 'Pagamento' }}:
204
-                  <strong>€ {{ number_format($pagamento->importo, 2, ',', '.') }}</strong>
205
-                  <small class="text-muted">({{ $pagamento->stato ?? '' }})</small>
206
-                  <i class="bx bx-right-arrow-alt"></i>
207
-                </span>
208
-              </li> -->
209
-              <li class="report-list-item-li p-2 rounded-3 transition-all duration-300">
210
-              <div class="report-list-item rounded-2">
211
-                <div class="d-flex align-items-center">
212
-                  <div class="report-list-icon shadow-xs me-4">
213
-                  <span class="fs-4 badge rounded-2 bg-label-secondary p-2 ">
214
-                    @switch($pagamento->metodo_pagamento->tipo)
215
-                    @case('carta_di_credito')
216
-                      <i class="bx bx-credit-card"></i>
217
-                      @break
218
-                    @case('carta_di_debito')
219
-                    
220
-                      <i class="bx bx-credit-card"></i>
221
-                      @break
222
-                    @case('bonifico')
223
-                      <i class="bx bx-transfer"></i>
224
-                      @break
225
-                    @case('paypal')
226
-                      <i class="bx bx-paypal"></i>
227
-                      @break
228
-                    @case('stripe')
229
-                      <i class="bx bx-credit-card"></i>
230
-                      @break
231
-                    @case('contanti')
232
-                      <i class="bx bx-money"></i>
233
-                      @break
234
-                    @case('credito')
235
-                      <i class="bx bx-wallet"></i>
236
-                      @break
237
-                    @case('apple_pay')
238
-                      <i class="bx bx-mobile"></i>
239
-                      @break
240
-                    @case('google_pay')
241
-                      <i class="bx bx-mobile"></i>
242
-                      @break
243
-                    @case('cupon')
244
-                      <i class="bx bx-purchase-tag"></i>
245
-                      @break
246
-                    @case('segresta_wallet')
247
-                      <i class="bx bx-wallet"></i>
248
-                      @break
249
-                    @case('pos')
250
-                      <i class="bx bx-credit-card"></i>
251
-                      @break
252
-                    @default
253
-                      <i class="bx bx-credit-card"></i>
254
-                      @break
255
-                    @endswitch
256
-                    </span>
257
-                  </div>
258
-                  <div class="d-flex justify-content-between align-items-center w-100 flex-wrap gap-2">
259
-                    <div class="d-flex flex-column">
260
-                      <span>{{ $pagamento->metodo_pagamento->nome ?? 'Pagamento' }}</span>
261
-                      <small class="text-success">{!! view('prenotazione._partials.stato-prenotazione', ['stato' => $ordine->stato]) !!}</small>
262
-                    </div>
263
-                    <h5 class="mb-0" id="importo-totale">€ {{ number_format($pagamento->importo, 2, ',', '.') }}</h5>
264
-                  </div>
388
+
389
+          @forelse($ordine->pagamenti as $pagamento)
390
+            <a href="{{ route('pagamento.show', ['pagamento_id' => $pagamento->id]) }}" class="or-show-link-card text-body text-decoration-none">
391
+              <div class="or-show-link-card__icon">
392
+                <i class="bx {{ $iconePagamento[$pagamento->metodo_pagamento->tipo ?? ''] ?? 'bx-credit-card' }}"></i>
393
+              </div>
394
+              <div class="or-show-link-card__body">
395
+                <div class="or-show-link-card__label">Pagamento #{{ $pagamento->id }}</div>
396
+                <div class="or-show-link-card__title">
397
+                  {{ $pagamento->metodo_pagamento->nome ?? 'Pagamento' }}
398
+                  · € {{ number_format((float) $pagamento->importo, 2, ',', '.') }}
399
+                </div>
400
+                <div class="or-show-link-card__subtitle">
401
+                  @include('prenotazione._partials.stato-prenotazione', ['stato' => $pagamento->stato])
265
                 </div>
402
                 </div>
266
               </div>
403
               </div>
267
-              </li>
268
-            @endforeach
269
-          </ul>
270
-        </div>
271
-        @endif
272
-        @if(isset($ordine->cliente) && $ordine->cliente)
273
-        <div class="mb-3">
274
-          <h6 class="fw-bold mb-2">Cliente</h6>
275
-          <div><i class="bx bx-user"></i> {{ $ordine->cliente->nome ?? '' }} {{ $ordine->cliente->cognome ?? '' }}</div>
404
+              <i class="bx bx-chevron-right text-muted"></i>
405
+            </a>
406
+          @empty
407
+            <div class="or-show-link-card or-show-link-card--empty">
408
+              <div class="or-show-link-card__icon"><i class="bx bx-money"></i></div>
409
+              <div class="or-show-link-card__body">
410
+                <div class="or-show-link-card__label">Pagamento</div>
411
+                <div class="or-show-link-card__title text-muted">Nessun pagamento</div>
412
+              </div>
413
+            </div>
414
+          @endforelse
276
         </div>
415
         </div>
277
-        @endif
278
-        <!-- Puoi aggiungere qui ulteriori entità correlate -->
279
       </div>
416
       </div>
280
     </div>
417
     </div>
281
   </div>
418
   </div>
282
 </div>
419
 </div>
283
-
284
-<div class="modal fade" id="basicModal" tabindex="-1" aria-hidden="true">
285
-            <div class="modal-dialog" role="document">
286
-              <div class="modal-content">
287
-                <div class="modal-header">
288
-                  <h5 class="modal-title" id="exampleModalLabel1">Modal title</h5>
289
-                  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
290
-                </div>
291
-                <div class="modal-body">
292
-                  <div class="row">
293
-                    <div class="col mb-6">
294
-                      <label for="nameBasic" class="form-label">Name</label>
295
-                      <input type="text" id="nameBasic" class="form-control" placeholder="Enter Name">
296
-                    </div>
297
-                  </div>
298
-                  <div class="row g-6">
299
-                    <div class="col mb-0">
300
-                      <label for="emailBasic" class="form-label">Email</label>
301
-                      <input type="email" id="emailBasic" class="form-control" placeholder="xxxx@xxx.xx">
302
-                    </div>
303
-                    <div class="col mb-0">
304
-                      <label for="dobBasic" class="form-label">DOB</label>
305
-                      <input type="date" id="dobBasic" class="form-control">
306
-                    </div>
307
-                  </div>
308
-                </div>
309
-                <div class="modal-footer">
310
-                  <button type="button" class="btn btn-label-secondary" data-bs-dismiss="modal">Close</button>
311
-                  <button type="button" class="btn btn-primary">Save changes</button>
312
-                </div>
313
-              </div>
314
-            </div>
315
-          </div>
316
-
317
-@endsection
318
-
319
-@section('page-script')
320
-
321
-<script>
322
-    document.addEventListener('DOMContentLoaded', function() {
323
-
324
-        function verificaTotale() {
325
-            $.ajax({
326
-                url: "{{ route('carrello.totale') }}",
327
-                type: "GET",
328
-                data: {
329
-                    dispositivo_id: "{{ $ordine->dispositivo_id }}",
330
-                    attivita_id: "{{ $ordine->attivita_id }}",
331
-                    ordine_id: "{{ $ordine->id }}",
332
-                },
333
-                success: function(response){
334
-                    // console.log(response['totale']);
335
-                    // totale_pagamenti = parseFloat(response['totale']);
336
-                    // Normalizza entrambi i totali come numeri decimali con due cifre dopo la virgola (es: "00.00")
337
-                    var totaleCarrello = parseFloat(response['totale'] || 0).toFixed(2);
338
-                    var totaleRigheOrdine = parseFloat("{{ number_format($ordine->righe_ordine->sum('prezzo'), 2, '.', '') }}").toFixed(2);
339
-                    // alert([totaleCarrello , totaleRigheOrdine , (totaleCarrello !== totaleRigheOrdine)]);
340
-                    if (totaleCarrello !== totaleRigheOrdine) {
341
-                        // alert("Il totale del carrello è diverso dal totale del pagamento");
342
-                        window.location.reload();
343
-                    }
344
-                    // alert("Il totale del carrello è uguale al totale del pagamento");
345
-                },
346
-                error: function(xhr, status, error){
347
-                    console.log(xhr.responseText);
348
-                }
349
-            });
350
-        }
351
-
352
-        setInterval(verificaTotale, 1500); // Esegui la funzione ogni 1500ms (1.5 secondi)
353
-    });
354
-</script>
355
-
356
 @endsection
420
 @endsection

+ 87
- 6
resources/views/punto_vendita/cassa/_partials/carrello/pagamento/checkout.blade.php Просмотреть файл

161
                     @if($metodo->tipo == MetodoPagamento::SEGRESTA_WALLET)
161
                     @if($metodo->tipo == MetodoPagamento::SEGRESTA_WALLET)
162
                       class="form-check-input segrestaWalletInput"
162
                       class="form-check-input segrestaWalletInput"
163
                       data-tipo="{{ MetodoPagamento::SEGRESTA_WALLET }}"
163
                       data-tipo="{{ MetodoPagamento::SEGRESTA_WALLET }}"
164
+                    @elseif($metodo->tipo == MetodoPagamento::CUPON)
165
+                      class="form-check-input cuponInput"
166
+                      data-tipo="{{ MetodoPagamento::CUPON }}"
164
                     @else
167
                     @else
165
                       class="form-check-input"
168
                       class="form-check-input"
166
                     @endif
169
                     @endif
185
                     Scansiona un braccialetto NFC valido per pagare con Segresta Wallet.
188
                     Scansiona un braccialetto NFC valido per pagare con Segresta Wallet.
186
                   </span>
189
                   </span>
187
                 @endif
190
                 @endif
191
+                @if($metodo->tipo == MetodoPagamento::CUPON)
192
+                  <div class="mt-2 p-3 border rounded bg-lighter" id="cuponAlert" style="display: none;">
193
+                    <label class="form-label small fw-medium mb-1" for="cuponCode">Codice coupon</label>
194
+                    <div class="input-group input-group-sm">
195
+                      <input type="text" class="form-control" id="cuponCode" name="cupon_codice" placeholder="Inserisci codice..." autocomplete="off">
196
+                      <button type="button" class="btn btn-outline-primary" id="btnCheckCupon">
197
+                        <i class="bx bx-search-alt"></i>
198
+                      </button>
199
+                    </div>
200
+                    <div id="cuponFeedback" class="mt-2" style="display: none;">
201
+                      <div id="cuponCheckMessage" class="small fw-medium mb-1"></div>
202
+                      <div class="d-flex flex-wrap gap-2 small text-muted">
203
+                        <span id="cuponImporto" style="display: none;"></span>
204
+                        <span id="cuponNominativo" style="display: none;"></span>
205
+                        <span id="cuponValiditaDa" style="display: none;"></span>
206
+                        <span id="cuponValiditaA" style="display: none;"></span>
207
+                      </div>
208
+                    </div>
209
+                  </div>
210
+                @endif
188
               </div>
211
               </div>
189
             </div>
212
             </div>
190
           @endforeach
213
           @endforeach
219
       checkUX($(this));
242
       checkUX($(this));
220
 
243
 
221
   });
244
   });
245
+
246
+  $('#cuponCode').on('input', function(){
247
+    var val = $(this).val().trim();
248
+    if(val.length >= 3) {
249
+      checkCupon(val);
250
+    } else {
251
+      resetCuponFeedback();
252
+      $('button[type="submit"]').prop('disabled', true);
253
+    }
254
+  });
255
+
256
+  $('#btnCheckCupon').on('click', function(){
257
+    var val = $('#cuponCode').val().trim();
258
+    if(val.length > 0) checkCupon(val);
259
+  });
222
 });
260
 });
223
 
261
 
224
 function checkUX(input){
262
 function checkUX(input){
227
       // 
265
       // 
228
 
266
 
229
 
267
 
268
+      $('#segrestaWalletAlertToScan').hide();
269
+      $('#cuponAlert').hide();
270
+      resetCuponFeedback();
271
+
230
       if(input.data('tipo') == "{{ MetodoPagamento::SEGRESTA_WALLET }}"){
272
       if(input.data('tipo') == "{{ MetodoPagamento::SEGRESTA_WALLET }}"){
231
         $('#segrestaWalletAlertToScan').show();
273
         $('#segrestaWalletAlertToScan').show();
232
         $('button[type="submit"]').prop('disabled', true);
274
         $('button[type="submit"]').prop('disabled', true);
233
         scanningNfcRequest();
275
         scanningNfcRequest();
234
-      
235
-    }else{
236
-      $('#segrestaWalletAlertToScan').hide();
237
-      $('button[type="submit"]').prop('disabled', false);
238
-      ;
239
-    }
276
+      } else if(input.data('tipo') == "{{ MetodoPagamento::CUPON }}"){
277
+        $('#cuponAlert').show();
278
+        $('#cuponCode').val('');
279
+        $('button[type="submit"]').prop('disabled', true);
280
+      } else {
281
+        $('button[type="submit"]').prop('disabled', false);
282
+      }
240
   
283
   
241
 }
284
 }
242
 
285
 
283
   });
326
   });
284
 }
327
 }
285
 
328
 
329
+function resetCuponFeedback(){
330
+  $('#cuponFeedback').hide();
331
+  $('#cuponCheckMessage').text('').removeClass('text-success text-danger');
332
+  $('#cuponImporto, #cuponNominativo, #cuponValiditaDa, #cuponValiditaA').hide().text('');
333
+}
334
+
335
+function checkCupon(codice) {
336
+  resetCuponFeedback();
337
+  $.ajax({
338
+    url: "{{ route('cupon.check') }}",
339
+    type: 'POST',
340
+    data: {
341
+      cupon_codice: codice,
342
+      _token: "{{ csrf_token() }}",
343
+      ordine_id: "{{ $ordine->id }}"
344
+    },
345
+    success: function(response){
346
+      $('#cuponFeedback').show();
347
+      if(response.success){
348
+        $('#cuponCheckMessage').addClass('text-success').text(response.message);
349
+        if(response.importo) $('#cuponImporto').show().html('<i class="bx bx-euro"></i> '+response.importo);
350
+        if(response.nominativo) $('#cuponNominativo').show().html('<i class="bx bx-user"></i> '+response.nominativo);
351
+        if(response.validita_da) $('#cuponValiditaDa').show().html('<i class="bx bx-calendar"></i> da '+response.validita_da);
352
+        if(response.validita_a) $('#cuponValiditaA').show().html('<i class="bx bx-calendar-check"></i> a '+response.validita_a);
353
+        $('button[type="submit"]').prop('disabled', false);
354
+      } else {
355
+        $('#cuponCheckMessage').addClass('text-danger').text(response.message);
356
+        $('button[type="submit"]').prop('disabled', true);
357
+      }
358
+    },
359
+    error: function(){
360
+      $('#cuponFeedback').show();
361
+      $('#cuponCheckMessage').addClass('text-danger').text('Errore di connessione. Riprova.');
362
+      $('button[type="submit"]').prop('disabled', true);
363
+    }
364
+  });
365
+}
366
+
286
 /////////////////////// spostato in INDEX
367
 /////////////////////// spostato in INDEX
287
 // let nfcAbortController = null;
368
 // let nfcAbortController = null;
288
 
369
 

+ 8
- 8
resources/views/punto_vendita/cassa/viste/catalogo/index.blade.php Просмотреть файл

117
           <a class="dropdown-item text-danger" href="javascript:void(0);" onclick="dissociaDispositivo()">
117
           <a class="dropdown-item text-danger" href="javascript:void(0);" onclick="dissociaDispositivo()">
118
             <i class="bx bx-unlink me-2"></i>Dissocia dispositivo
118
             <i class="bx bx-unlink me-2"></i>Dissocia dispositivo
119
           </a>
119
           </a>
120
-        </div>
120
+    </div>
121
       </div>
121
       </div>
122
 
122
 
123
       <!-- <a href="{{ route('punto-vendita.show', ['punto_vendita_id' => $punto_vendita->id , 'vista' => 'catalogo']) }}" class=" ms-2 px-3 py-1 alert text-bg-primary"> 
123
       <!-- <a href="{{ route('punto-vendita.show', ['punto_vendita_id' => $punto_vendita->id , 'vista' => 'catalogo']) }}" class=" ms-2 px-3 py-1 alert text-bg-primary"> 
265
               @endforeach
265
               @endforeach
266
             @endforeach
266
             @endforeach
267
           </div>
267
           </div>
268
-        </div>
268
+          </div>
269
         </div>
269
         </div>
270
       </div>
270
       </div>
271
     </section>
271
     </section>
335
 
335
 
336
               </div>
336
               </div>
337
               </div>
337
               </div>
338
-            </div>
339
-          </div>
340
-          
338
+  </div>
339
+</div>
340
+
341
 <script>
341
 <script>
342
   (function () {
342
   (function () {
343
     const KITCHEN_PAGE_SIZE = 10;
343
     const KITCHEN_PAGE_SIZE = 10;
511
         if (isPreOrdine) {
511
         if (isPreOrdine) {
512
           selectedKitchenLabel.textContent = 'Pre-ordine';
512
           selectedKitchenLabel.textContent = 'Pre-ordine';
513
         } else {
513
         } else {
514
-          const labelEl = selectedTab ? selectedTab.querySelector('.cassa-sb-kitchen-label') : null;
515
-          selectedKitchenLabel.textContent = labelEl ? labelEl.textContent.trim() : 'Tutte';
516
-        }
514
+        const labelEl = selectedTab ? selectedTab.querySelector('.cassa-sb-kitchen-label') : null;
515
+        selectedKitchenLabel.textContent = labelEl ? labelEl.textContent.trim() : 'Tutte';
516
+      }
517
       }
517
       }
518
 
518
 
519
       if (isPreOrdine) {
519
       if (isPreOrdine) {

Загрузка…
Отмена
Сохранить