673 lines
34 KiB
PHP
673 lines
34 KiB
PHP
<?php
|
|
include('include/headscript.php');
|
|
|
|
if (!isset($iduserlogin)) die("Errore: utente non loggato.");
|
|
|
|
$dbHandler = DBHandlerSelect::getInstance();
|
|
$pdo = $dbHandler->getConnection();
|
|
|
|
// Recupera la scuola
|
|
$stmt = $pdo->prepare("SELECT id, name FROM schools WHERE owner_id = ?");
|
|
$stmt->execute([$iduserlogin]);
|
|
$school = $stmt->fetch();
|
|
if (!$school) die("Scuola non trovata.");
|
|
$school_id = (int)$school['id'];
|
|
|
|
|
|
// === UTENTI DELLA SCUOLA (dropdown cercabile) ===
|
|
$stmtUsers = $pdo->prepare("
|
|
SELECT au.id, au.first_name, au.last_name, au.email
|
|
FROM user_schools us
|
|
JOIN auth_users au ON au.id = us.user_id
|
|
WHERE us.school_id = ?
|
|
AND us.status = 'active'
|
|
ORDER BY au.first_name, au.last_name
|
|
");
|
|
$stmtUsers->execute([$school_id]);
|
|
$schoolUsers = $stmtUsers->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// === PRODOTTI ATTIVI ===
|
|
$stmtProd = $pdo->prepare("
|
|
SELECT id, name, type
|
|
FROM products
|
|
WHERE school_id = ? AND status = 'active'
|
|
ORDER BY name
|
|
");
|
|
$stmtProd->execute([$school_id]);
|
|
$products = $stmtProd->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// === VARIAZIONI ATTIVE (per filtro lato JS) ===
|
|
$variations = [];
|
|
if (!empty($products)) {
|
|
$prodIds = array_column($products, 'id');
|
|
$in = implode(',', array_fill(0, count($prodIds), '?'));
|
|
|
|
$stmtVar = $pdo->prepare("
|
|
SELECT id, product_id, name, price, duration_days, max_entries, max_recoveries
|
|
FROM product_variations
|
|
WHERE product_id IN ($in)
|
|
AND status = 'active'
|
|
ORDER BY product_id, name
|
|
");
|
|
$stmtVar->execute($prodIds);
|
|
$variations = $stmtVar->fetchAll(PDO::FETCH_ASSOC);
|
|
}
|
|
|
|
// === CLASSI ATTIVE ===
|
|
$stmtClasses = $pdo->prepare("
|
|
SELECT id, name
|
|
FROM classes
|
|
WHERE school_id = ? AND status = 'active'
|
|
ORDER BY name
|
|
");
|
|
$stmtClasses->execute([$school_id]);
|
|
$classes = $stmtClasses->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
// === CLASS TYPES (filtrati lato JS per class_id) ===
|
|
$stmtCT = $pdo->prepare("
|
|
SELECT ct.id, ct.class_id, ct.level, ct.day_of_week
|
|
FROM class_types ct
|
|
JOIN classes c ON ct.class_id = c.id
|
|
WHERE c.school_id = ?
|
|
ORDER BY c.name, ct.day_of_week, ct.level
|
|
");
|
|
$stmtCT->execute([$school_id]);
|
|
$classTypes = $stmtCT->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
$feedback = '';
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$action = $_POST['action'] ?? '';
|
|
|
|
if ($action === 'add_order_manual') {
|
|
$user_id = (int)($_POST['user_id'] ?? 0);
|
|
$product_id = (int)($_POST['product_id'] ?? 0);
|
|
$variation_id = (int)($_POST['variation_id'] ?? 0);
|
|
$payment_method = trim($_POST['payment_method'] ?? '');
|
|
$status = trim($_POST['status'] ?? 'completed');
|
|
|
|
$price = isset($_POST['price']) ? (float)str_replace(',', '.', $_POST['price']) : 0.0;
|
|
$total_entries = ($_POST['total_entries'] ?? '') !== '' ? (int)$_POST['total_entries'] : null;
|
|
$available_entries = ($_POST['available_entries'] ?? '') !== '' ? (int)$_POST['available_entries'] : null;
|
|
|
|
$activation_date = $_POST['activation_date'] ?? date('Y-m-d');
|
|
$expiration_date = $_POST['expiration_date'] ?? null;
|
|
$expiration_date = ($expiration_date === '') ? null : $expiration_date;
|
|
|
|
$class_id = ($_POST['class_id'] ?? '') !== '' ? (int)$_POST['class_id'] : null;
|
|
$class_type_id = ($_POST['class_type_id'] ?? '') !== '' ? (int)$_POST['class_type_id'] : null;
|
|
|
|
// Validazioni base
|
|
if ($user_id <= 0 || $product_id <= 0 || $payment_method === '') {
|
|
$feedback = '<div class="alert alert-danger alert-dismissible fade show">Compila utente, prodotto e metodo di pagamento.<button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>';
|
|
} else {
|
|
// 1) utente appartiene alla scuola
|
|
$stmt = $pdo->prepare("SELECT 1 FROM user_schools WHERE school_id = ? AND user_id = ? AND status='active' LIMIT 1");
|
|
$stmt->execute([$school_id, $user_id]);
|
|
if (!$stmt->fetchColumn()) {
|
|
$feedback = '<div class="alert alert-danger alert-dismissible fade show">Utente non associato alla scuola.<button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>';
|
|
} else {
|
|
// 2) prodotto appartiene alla scuola
|
|
$stmt = $pdo->prepare("SELECT id FROM products WHERE id=? AND school_id=? AND status='active' LIMIT 1");
|
|
$stmt->execute([$product_id, $school_id]);
|
|
if (!$stmt->fetchColumn()) {
|
|
$feedback = '<div class="alert alert-danger alert-dismissible fade show">Prodotto non valido.<button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>';
|
|
} else {
|
|
// 3) se variation_id valorizzato, deve appartenere al prodotto
|
|
$varMeta = null;
|
|
if ($variation_id > 0) {
|
|
$stmt = $pdo->prepare("SELECT id, price, duration_days, max_entries, max_recoveries FROM product_variations WHERE id=? AND product_id=? AND status='active' LIMIT 1");
|
|
$stmt->execute([$variation_id, $product_id]);
|
|
$varMeta = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
if (!$varMeta) {
|
|
$feedback = '<div class="alert alert-danger alert-dismissible fade show">Variazione non valida.<button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>';
|
|
}
|
|
}
|
|
|
|
if ($feedback === '') {
|
|
// 4) class / class_type se presenti devono essere coerenti e della scuola
|
|
if ($class_id) {
|
|
$stmt = $pdo->prepare("SELECT 1 FROM classes WHERE id=? AND school_id=? LIMIT 1");
|
|
$stmt->execute([$class_id, $school_id]);
|
|
if (!$stmt->fetchColumn()) {
|
|
$feedback = '<div class="alert alert-danger alert-dismissible fade show">Classe non valida.<button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>';
|
|
}
|
|
}
|
|
if ($class_type_id) {
|
|
$stmt = $pdo->prepare("
|
|
SELECT 1
|
|
FROM class_types ct
|
|
JOIN classes c ON ct.class_id = c.id
|
|
WHERE ct.id=? AND c.school_id=?
|
|
LIMIT 1
|
|
");
|
|
$stmt->execute([$class_type_id, $school_id]);
|
|
if (!$stmt->fetchColumn()) {
|
|
$feedback = '<div class="alert alert-danger alert-dismissible fade show">Class type non valido.<button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>';
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($feedback === '') {
|
|
// Autocomplete intelligente da variazione se non inserito
|
|
if ($varMeta) {
|
|
if ($price <= 0) $price = (float)$varMeta['price'];
|
|
if ($total_entries === null && $varMeta['max_entries'] !== null) $total_entries = (int)$varMeta['max_entries'];
|
|
if ($available_entries === null && $total_entries !== null) $available_entries = $total_entries;
|
|
|
|
if (!$expiration_date && !empty($varMeta['duration_days'])) {
|
|
$d = new DateTime($activation_date);
|
|
$d->modify('+' . (int)$varMeta['duration_days'] . ' days');
|
|
$expiration_date = $d->format('Y-m-d');
|
|
}
|
|
$available_recoveries = ($varMeta['max_recoveries'] !== null) ? (int)$varMeta['max_recoveries'] : null;
|
|
} else {
|
|
$available_recoveries = null;
|
|
}
|
|
|
|
// order_number progressivo per scuola
|
|
try {
|
|
$pdo->beginTransaction();
|
|
|
|
$stmt = $pdo->prepare("SELECT COALESCE(MAX(order_number),0) + 1 FROM orders WHERE school_id=? FOR UPDATE");
|
|
$stmt->execute([$school_id]);
|
|
$nextOrderNumber = (int)$stmt->fetchColumn();
|
|
|
|
$stmtIns = $pdo->prepare("
|
|
INSERT INTO orders
|
|
(order_number, school_id, user_id, product_id, variation_id, class_id, class_type_id,
|
|
created_at, payment_method, price, status,
|
|
total_entries, available_entries, available_recoveries,
|
|
expiration_date, activation_date)
|
|
VALUES
|
|
(?, ?, ?, ?, ?, ?, ?,
|
|
NOW(), ?, ?, ?,
|
|
?, ?, ?,
|
|
?, ?)
|
|
");
|
|
|
|
$stmtIns->execute([
|
|
$nextOrderNumber,
|
|
$school_id,
|
|
$user_id,
|
|
$product_id,
|
|
($variation_id > 0 ? $variation_id : null),
|
|
$class_id,
|
|
$class_type_id,
|
|
$payment_method,
|
|
$price,
|
|
$status,
|
|
$total_entries,
|
|
$available_entries,
|
|
$available_recoveries,
|
|
$expiration_date,
|
|
$activation_date
|
|
]);
|
|
|
|
$pdo->commit();
|
|
|
|
$feedback = '<div class="alert alert-success alert-dismissible fade show">Ordine manuale inserito con successo!<button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>';
|
|
} catch (Exception $e) {
|
|
if ($pdo->inTransaction()) $pdo->rollBack();
|
|
$feedback = '<div class="alert alert-danger alert-dismissible fade show">Errore inserimento ordine: ' . htmlspecialchars($e->getMessage()) . '<button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Recupera tutti gli ordini con tutti i dati necessari
|
|
$stmt = $pdo->prepare("
|
|
SELECT
|
|
o.id,
|
|
o.order_number,
|
|
o.created_at,
|
|
o.price,
|
|
o.status,
|
|
o.payment_method,
|
|
o.total_entries,
|
|
o.available_entries,
|
|
o.expiration_date,
|
|
u.first_name,
|
|
u.last_name,
|
|
u.email,
|
|
p.name AS product_name,
|
|
pv.name AS variation_name,
|
|
c.name AS class_name,
|
|
ct.level,
|
|
ct.day_of_week
|
|
FROM orders o
|
|
JOIN auth_users u ON o.user_id = u.id
|
|
JOIN products p ON o.product_id = p.id
|
|
LEFT JOIN product_variations pv ON o.variation_id = pv.id
|
|
LEFT JOIN classes c ON o.class_id = c.id
|
|
LEFT JOIN class_types ct ON o.class_type_id = ct.id
|
|
WHERE o.school_id = ?
|
|
ORDER BY o.created_at DESC
|
|
");
|
|
$stmt->execute([$school_id]);
|
|
$orders = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
?>
|
|
|
|
<!doctype html>
|
|
<html lang="it">
|
|
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Ordini - <?php echo htmlspecialchars($school['name']); ?></title>
|
|
<?php include('cssinclude.php'); ?>
|
|
<?php include('siteinfo.php'); ?>
|
|
<link rel="stylesheet" href="assets/plugins/select2/css/select2.min.css">
|
|
|
|
<!-- DataTables CSS -->
|
|
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.7/css/dataTables.bootstrap5.min.css">
|
|
<link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.5.0/css/responsive.bootstrap5.min.css">
|
|
<link rel="stylesheet" href="https://cdn.datatables.net/buttons/2.4.2/css/buttons.bootstrap5.min.css">
|
|
</head>
|
|
|
|
<body>
|
|
<div class="wrapper">
|
|
<?php include('include/navbar.php'); ?>
|
|
<?php include('include/topbar.php'); ?>
|
|
|
|
<div class="page-wrapper">
|
|
<div class="page-content">
|
|
<div class="container-fluid px-1">
|
|
|
|
<div class="card radius-15 shadow-lg mb-4">
|
|
<div class="card-header bg-primary text-white d-flex justify-content-between align-items-center">
|
|
<h4 class="mb-0">
|
|
Gestione Ordini
|
|
<span class="badge bg-light text-dark ms-2"><?php echo count($orders); ?></span>
|
|
</h4>
|
|
<div class="d-flex gap-2">
|
|
<button type="button" class="btn btn-light btn-sm" data-bs-toggle="modal" data-bs-target="#manualOrderModal">
|
|
+ Ordine manuale
|
|
</button>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
<?php echo $feedback; ?>
|
|
|
|
<div class="card radius-15 shadow">
|
|
<div class="card-body p-0">
|
|
<div class="table-responsive">
|
|
<table id="ordersTable" class="table table-striped table-hover" style="width:100%">
|
|
<thead class="table-dark">
|
|
<tr>
|
|
<th>Data</th>
|
|
<th>Ordine #</th>
|
|
<th>Cliente</th>
|
|
<th>Email</th>
|
|
<th>Prodotto</th>
|
|
<th>Variazione</th>
|
|
<th>Prezzo</th>
|
|
<th>Ingressi</th>
|
|
<th>Scadenza</th>
|
|
<th>Stato</th>
|
|
<th>Pagamento</th>
|
|
<th>Lezione</th>
|
|
<th>Azioni</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($orders as $o): ?>
|
|
<tr>
|
|
<td data-order="<?php echo $o['created_at']; ?>">
|
|
<strong><?php echo date('d/m/Y', strtotime($o['created_at'])); ?></strong><br>
|
|
<small class="text-muted"><?php echo date('H:i', strtotime($o['created_at'])); ?></small>
|
|
</td>
|
|
<td><strong>#<?php echo $o['order_number']; ?></strong></td>
|
|
<td><?php echo htmlspecialchars($o['first_name'] . ' ' . $o['last_name']); ?></td>
|
|
<td>
|
|
<a href="mailto:<?php echo htmlspecialchars($o['email']); ?>">
|
|
<?php echo htmlspecialchars($o['email']); ?>
|
|
</a>
|
|
</td>
|
|
<td><?php echo htmlspecialchars($o['product_name']); ?></td>
|
|
<td><?php echo htmlspecialchars($o['variation_name'] ?: '-'); ?></td>
|
|
<td><strong>€<?php echo number_format($o['price'], 2); ?></strong></td>
|
|
<td>
|
|
<?php echo $o['total_entries'] ? $o['available_entries'] . '/' . $o['total_entries'] : 'Illimitati'; ?>
|
|
</td>
|
|
<td>
|
|
<?php if ($o['expiration_date']): ?>
|
|
<span class="text-danger fw-bold"><?php echo date('d/m/Y', strtotime($o['expiration_date'])); ?></span>
|
|
<?php else: ?>
|
|
<em>Nessuna</em>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<span class="badge <?php echo $o['status'] == 'completed' ? 'bg-success' : ($o['status'] == 'pending' ? 'bg-warning' : 'bg-secondary'); ?>">
|
|
<?php echo ucfirst($o['status']); ?>
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<span class="badge bg-info"><?php echo strtoupper($o['payment_method']); ?></span>
|
|
</td>
|
|
<td>
|
|
<?php if ($o['class_name']): ?>
|
|
<small>
|
|
<strong><?php echo htmlspecialchars($o['class_name']); ?></strong><br>
|
|
<?php echo ucfirst($o['level'] ?? ''); ?>
|
|
(<?php echo ucfirst($o['day_of_week'] ?? 'qualsiasi'); ?>)
|
|
</small>
|
|
<?php else: ?>
|
|
<em>Tutte le classi</em>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<div class="btn-group" role="group">
|
|
<button type="button" class="btn btn-sm btn-outline-primary">Dettaglio</button>
|
|
<button type="button" class="btn btn-sm btn-outline-success">Prenotazioni</button>
|
|
<button type="button" class="btn btn-sm btn-outline-warning">Email</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal fade" id="manualOrderModal" tabindex="-1">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<form method="POST">
|
|
<input type="hidden" name="action" value="add_order_manual">
|
|
|
|
<div class="modal-header bg-primary text-white">
|
|
<h5 class="modal-title">Inserisci ordine manuale</h5>
|
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
|
</div>
|
|
|
|
<div class="modal-body">
|
|
<div class="row g-3">
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label">Utente</label>
|
|
<select name="user_id" class="form-select select2-user" required data-placeholder="Cerca per nome o email">
|
|
<option value=""></option>
|
|
<?php foreach ($schoolUsers as $u): ?>
|
|
<option value="<?php echo (int)$u['id']; ?>">
|
|
<?php
|
|
$full = trim(($u['first_name'] ?? '') . ' ' . ($u['last_name'] ?? ''));
|
|
echo htmlspecialchars($full . ' — ' . ($u['email'] ?? ''));
|
|
?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label">Metodo pagamento</label>
|
|
<select name="payment_method" class="form-select" required>
|
|
<option value="">Seleziona...</option>
|
|
<option value="cash">Cash</option>
|
|
<option value="pos">POS</option>
|
|
<option value="bank_transfer">Bonifico</option>
|
|
<option value="manual">Manuale</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label">Prodotto</label>
|
|
<select name="product_id" class="form-select select2-product" required data-placeholder="Seleziona prodotto">
|
|
<option value=""></option>
|
|
<?php foreach ($products as $p): ?>
|
|
<option value="<?php echo (int)$p['id']; ?>">
|
|
<?php echo htmlspecialchars($p['name']); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label">Variazione</label>
|
|
<select name="variation_id" class="form-select select2-variation" data-placeholder="(opzionale)">
|
|
<option value=""></option>
|
|
<?php foreach ($variations as $v): ?>
|
|
<option
|
|
value="<?php echo (int)$v['id']; ?>"
|
|
data-product-id="<?php echo (int)$v['product_id']; ?>"
|
|
data-price="<?php echo htmlspecialchars($v['price']); ?>"
|
|
data-duration-days="<?php echo (int)($v['duration_days'] ?? 0); ?>"
|
|
data-max-entries="<?php echo ($v['max_entries'] !== null ? (int)$v['max_entries'] : ''); ?>">
|
|
<?php echo htmlspecialchars($v['name']); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<small class="text-muted">Le variazioni verranno filtrate in base al prodotto.</small>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<label class="form-label">Prezzo (€)</label>
|
|
<input type="text" name="price" class="form-control" placeholder="es. 49.90">
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<label class="form-label">Stato</label>
|
|
<select name="status" class="form-select">
|
|
<option value="completed" selected>completed</option>
|
|
<option value="pending">pending</option>
|
|
<option value="cancelled">cancelled</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<label class="form-label">Attivazione</label>
|
|
<input type="date" name="activation_date" class="form-control" value="<?php echo date('Y-m-d'); ?>">
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<label class="form-label">Ingressi totali</label>
|
|
<input type="number" name="total_entries" class="form-control" min="0" placeholder="(vuoto = illimitati)">
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<label class="form-label">Ingressi disponibili</label>
|
|
<input type="number" name="available_entries" class="form-control" min="0" placeholder="(auto)">
|
|
</div>
|
|
|
|
<div class="col-md-4">
|
|
<label class="form-label">Scadenza</label>
|
|
<input type="date" name="expiration_date" class="form-control" placeholder="(auto se duration)">
|
|
</div>
|
|
|
|
<?php if (isset($classes, $classTypes)): ?>
|
|
<hr class="my-2">
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label">Classe (opzionale)</label>
|
|
<select name="class_id" class="form-select select2-class" data-placeholder="Tutte le classi">
|
|
<option value=""></option>
|
|
<?php foreach ($classes as $c): ?>
|
|
<option value="<?php echo (int)$c['id']; ?>"><?php echo htmlspecialchars($c['name']); ?></option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<label class="form-label">Class Type (opzionale)</label>
|
|
<select name="class_type_id" class="form-select select2-classtype" data-placeholder="Qualsiasi">
|
|
<option value=""></option>
|
|
<?php foreach ($classTypes as $ct): ?>
|
|
<option value="<?php echo (int)$ct['id']; ?>" data-class-id="<?php echo (int)$ct['class_id']; ?>">
|
|
<?php echo htmlspecialchars(($ct['day_of_week'] ?? '') . ' - ' . ($ct['level'] ?? '')); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annulla</button>
|
|
<button type="submit" class="btn btn-primary">Salva ordine</button>
|
|
</div>
|
|
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<?php include('include/footer.php'); ?>
|
|
</div>
|
|
|
|
<?php include('jsinclude.php'); ?>
|
|
<script src="assets/plugins/select2/js/select2.min.js"></script>
|
|
|
|
<!-- DataTables + Plugin -->
|
|
<script src="https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js"></script>
|
|
<script src="https://cdn.datatables.net/1.13.7/js/dataTables.bootstrap5.min.js"></script>
|
|
<script src="https://cdn.datatables.net/responsive/2.5.0/js/dataTables.responsive.min.js"></script>
|
|
<script src="https://cdn.datatables.net/responsive/2.5.0/js/responsive.bootstrap5.min.js"></script>
|
|
<script src="https://cdn.datatables.net/buttons/2.4.2/js/dataTables.buttons.min.js"></script>
|
|
<script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.bootstrap5.min.js"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
|
|
<script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.html5.min.js"></script>
|
|
|
|
<script>
|
|
$(document).ready(function() {
|
|
$('#ordersTable').DataTable({
|
|
language: {
|
|
url: "//cdn.datatables.net/plug-ins/1.10.25/i18n/Italian.json"
|
|
},
|
|
pageLength: 25,
|
|
lengthMenu: [10, 25, 50, 100],
|
|
order: [
|
|
[0, 'desc']
|
|
],
|
|
responsive: true,
|
|
dom: 'Bfrtip',
|
|
buttons: [{
|
|
extend: 'excelHtml5',
|
|
text: 'Esporta Excel',
|
|
className: 'btn btn-success btn-sm'
|
|
},
|
|
{
|
|
extend: 'csvHtml5',
|
|
text: 'Esporta CSV',
|
|
className: 'btn btn-info btn-sm'
|
|
}
|
|
],
|
|
columnDefs: [{
|
|
targets: '_all',
|
|
className: 'text-center'
|
|
},
|
|
{
|
|
targets: 12,
|
|
orderable: false
|
|
}
|
|
]
|
|
});
|
|
});
|
|
</script>
|
|
<script>
|
|
$(function() {
|
|
// Select2 dentro modale
|
|
$('#manualOrderModal').on('shown.bs.modal', function() {
|
|
const $m = $('#manualOrderModal');
|
|
|
|
function initSel(selector) {
|
|
const $el = $m.find(selector);
|
|
if (!$el.length) return;
|
|
if ($el.hasClass('select2-hidden-accessible')) return;
|
|
$el.select2({
|
|
dropdownParent: $m,
|
|
width: '100%',
|
|
allowClear: true,
|
|
placeholder: $el.data('placeholder') || 'Seleziona...'
|
|
});
|
|
}
|
|
|
|
initSel('.select2-user');
|
|
initSel('.select2-product');
|
|
initSel('.select2-variation');
|
|
initSel('.select2-class');
|
|
initSel('.select2-classtype');
|
|
});
|
|
|
|
// Filtra variazioni in base al prodotto
|
|
$(document).on('change', 'select[name="product_id"]', function() {
|
|
const pid = $(this).val();
|
|
const $var = $('#manualOrderModal').find('select[name="variation_id"]');
|
|
|
|
$var.val('').trigger('change');
|
|
|
|
$var.find('option').each(function() {
|
|
const optPid = $(this).data('product-id');
|
|
if (!optPid) return; // option vuota
|
|
$(this).toggle(String(optPid) === String(pid));
|
|
});
|
|
});
|
|
|
|
// Quando selezioni una variazione: precompila prezzo + ingressi + scadenza
|
|
$(document).on('change', '#manualOrderModal select[name="variation_id"]', function() {
|
|
const $m = $('#manualOrderModal');
|
|
const $opt = $(this).find('option:selected');
|
|
|
|
const price = $opt.data('price');
|
|
const maxEntries = $opt.data('max-entries');
|
|
const durationDays = parseInt($opt.data('duration-days') || 0, 10);
|
|
|
|
// Prezzo
|
|
if (price !== undefined && price !== '') {
|
|
$m.find('input[name="price"]').val(price);
|
|
}
|
|
|
|
// Ingressi
|
|
if (maxEntries !== undefined && maxEntries !== '') {
|
|
$m.find('input[name="total_entries"]').val(maxEntries);
|
|
$m.find('input[name="available_entries"]').val(maxEntries);
|
|
}
|
|
|
|
// Scadenza (activation_date + durationDays)
|
|
const act = $m.find('input[name="activation_date"]').val();
|
|
if (durationDays > 0 && act) {
|
|
const d = new Date(act);
|
|
d.setDate(d.getDate() + durationDays);
|
|
|
|
const yyyy = d.getFullYear();
|
|
const mm = String(d.getMonth() + 1).padStart(2, '0');
|
|
const dd = String(d.getDate()).padStart(2, '0');
|
|
|
|
$m.find('input[name="expiration_date"]').val(`${yyyy}-${mm}-${dd}`);
|
|
}
|
|
});
|
|
|
|
|
|
// ricalcola scadenza se cambia activation_date (solo se variation con duration)
|
|
$(document).on('change', 'input[name="activation_date"]', function() {
|
|
$('select[name="variation_id"]').trigger('change');
|
|
});
|
|
|
|
// Filtra class_types in base alla classe
|
|
$(document).on('change', 'select[name="class_id"]', function() {
|
|
const cid = $(this).val();
|
|
const $ct = $('select[name="class_type_id"]');
|
|
|
|
$ct.val('').trigger('change');
|
|
|
|
$ct.find('option').each(function() {
|
|
const optCid = $(this).data('class-id');
|
|
if (!optCid) return;
|
|
$(this).toggle(String(optCid) === String(cid));
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|