Autosave: 20260217-062114
This commit is contained in:
parent
61ccd5cda6
commit
24ba5cd24a
498
pedidos.php
498
pedidos.php
@ -1,296 +1,248 @@
|
||||
<?php
|
||||
session_start();
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
header("Location: login.php");
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'db/config.php';
|
||||
include 'layout_header.php';
|
||||
|
||||
function getStatusStyle($status) {
|
||||
$style = 'color: white;'; // Default text color
|
||||
$bgColor = '#0dcaf0'; // Default info blue
|
||||
$db = db();
|
||||
$asesor_id = $_SESSION['user_id'];
|
||||
$role = $_SESSION['role'];
|
||||
|
||||
switch (strtoupper(trim($status))) {
|
||||
case 'ROTULADO':
|
||||
$bgColor = '#ffc107'; // yellow
|
||||
$style = 'color: black;';
|
||||
break;
|
||||
case 'EN TRANSITO':
|
||||
$bgColor = '#90EE90'; // light green
|
||||
$style = 'color: black;';
|
||||
break;
|
||||
case 'EN DESTINO':
|
||||
$bgColor = '#800080'; // purple
|
||||
break;
|
||||
case 'COMPLETADO':
|
||||
case 'COMPLETADO ✅':
|
||||
$bgColor = '#198754'; // dark green
|
||||
break;
|
||||
case 'GESTION':
|
||||
$bgColor = '#6c757d'; // secondary grey
|
||||
break;
|
||||
}
|
||||
return "background-color: {$bgColor} !important; {$style}";
|
||||
// Base query
|
||||
$sql = "SELECT p.*, u.username as asesor_nombre FROM pedidos p LEFT JOIN users u ON p.asesor_id = u.id WHERE 1=1";
|
||||
|
||||
// Filter by estado
|
||||
$estado = isset($_GET['estado']) ? $_GET['estado'] : 'pendiente';
|
||||
if ($estado) {
|
||||
$sql .= " AND p.estado = " . $db->quote($estado);
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
|
||||
$user_id = $_SESSION['user_id'];
|
||||
$user_role = $_SESSION['user_role'] ?? 'Asesor';
|
||||
|
||||
// Fetch years for the filter
|
||||
$years_query = "SELECT DISTINCT YEAR(created_at) as year FROM pedidos";
|
||||
if ($user_role === 'Asesor') {
|
||||
$years_query .= " WHERE asesor_id = ?";
|
||||
$years_stmt = $pdo->prepare($years_query);
|
||||
$years_stmt->execute([$user_id]);
|
||||
} else {
|
||||
$years_stmt = $pdo->query($years_query);
|
||||
}
|
||||
$years = $years_stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
|
||||
// Filter logic
|
||||
$selected_month = $_GET['mes'] ?? '';
|
||||
$selected_year = $_GET['año'] ?? '';
|
||||
$search_query = $_GET['q'] ?? '';
|
||||
|
||||
$sql = "SELECT p.*, u.nombre_asesor as asesor_nombre FROM pedidos p LEFT JOIN users u ON p.asesor_id = u.id WHERE p.estado = 'ROTULADO 📦'";
|
||||
$params = [];
|
||||
|
||||
if ($user_role === 'Asesor') {
|
||||
$sql .= " AND p.asesor_id = ?";
|
||||
$params[] = $user_id;
|
||||
// Filter by date
|
||||
$fecha = isset($_GET['fecha']) ? $_GET['fecha'] : '';
|
||||
if ($fecha) {
|
||||
$sql .= " AND p.fecha_pedido = " . $db->quote($fecha);
|
||||
}
|
||||
|
||||
if (!empty($search_query)) {
|
||||
$sql .= " AND (p.nombre_completo LIKE ? OR p.dni_cliente LIKE ? OR p.celular LIKE ?)";
|
||||
$params[] = "%$search_query%";
|
||||
$params[] = "%$search_query%";
|
||||
$params[] = "%$search_query%";
|
||||
// Filter by search term
|
||||
$search = isset($_GET['search']) ? $_GET['search'] : '';
|
||||
if ($search) {
|
||||
$searchTerm = '%' . $search . '%';
|
||||
$sql .= " AND (p.nombre_cliente LIKE " . $db->quote($searchTerm) . " OR p.celular_cliente LIKE " . $db->quote($searchTerm) . " OR p.guia LIKE " . $db->quote($searchTerm) . ")";
|
||||
}
|
||||
|
||||
if (!empty($selected_month)) {
|
||||
$sql .= " AND MONTH(p.created_at) = ?";
|
||||
$params[] = $selected_month;
|
||||
}
|
||||
if (!empty($selected_year)) {
|
||||
$sql .= " AND YEAR(p.created_at) = ?";
|
||||
$params[] = $selected_year;
|
||||
// Filter by asesor for non-admin roles
|
||||
if ($role !== 'admin') {
|
||||
$sql .= " AND p.asesor_id = " . $db->quote($asesor_id);
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY p.created_at DESC";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$pedidos = $stmt->fetchAll();
|
||||
$sql .= " ORDER BY p.id DESC";
|
||||
|
||||
$months = [
|
||||
1 => 'Enero', 2 => 'Febrero', 3 => 'Marzo', 4 => 'Abril', 5 => 'Mayo', 6 => 'Junio',
|
||||
7 => 'Julio', 8 => 'Agosto', 9 => 'Septiembre', 10 => 'Octubre', 11 => 'Noviembre', 12 => 'Diciembre'
|
||||
];
|
||||
|
||||
?>
|
||||
<?php
|
||||
$pageTitle = "Pedidos Rotulados";
|
||||
include 'layout_header.php';
|
||||
$result = $db->query($sql);
|
||||
?>
|
||||
|
||||
<?php if (isset($_SESSION['flash_message'])):
|
||||
$flash = $_SESSION['flash_message'];
|
||||
unset($_SESSION['flash_message']);
|
||||
?>
|
||||
<div class="alert alert-<?php echo htmlspecialchars($flash['type']); ?> alert-dismissible fade show" role="alert">
|
||||
<?php echo htmlspecialchars($flash['message']); ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
<div class="container-fluid mt-4">
|
||||
<h2>Gestión de Pedidos</h2>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
Filtros
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form method="GET" action="pedidos.php" class="row g-3">
|
||||
<div class="col-md-3">
|
||||
<label for="estado" class="form-label">Estado</label>
|
||||
<select name="estado" id="estado" class="form-select">
|
||||
<option value="pendiente" <?php echo ($estado == 'pendiente') ? 'selected' : ''; ?>>Pendiente</option>
|
||||
<option value="rotulado" <?php echo ($estado == 'rotulado') ? 'selected' : ''; ?>>Rotulado</option>
|
||||
<option value="EN TRANSITO" <?php echo ($estado == 'EN TRANSITO') ? 'selected' : ''; ?>>En Tránsito</option>
|
||||
<option value="completado" <?php echo ($estado == 'completado') ? 'selected' : ''; ?>>Completado</option>
|
||||
<option value="cancelado" <?php echo ($estado == 'cancelado') ? 'selected' : ''; ?>>Cancelado</option>
|
||||
<option value="gestion" <?php echo ($estado == 'gestion') ? 'selected' : ''; ?>>Gestión</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label for="fecha" class="form-label">Fecha</label>
|
||||
<input type="date" name="fecha" id="fecha" class="form-control" value="<?php echo htmlspecialchars($fecha); ?>">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="search" class="form-label">Buscar</label>
|
||||
<input type="text" name="search" id="search" class="form-control" placeholder="Nombre, celular, guía..." value="<?php echo htmlspecialchars($search); ?>">
|
||||
</div>
|
||||
<div class="col-md-2 d-flex align-items-end">
|
||||
<button type="submit" class="btn btn-primary">Filtrar</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (isset($_GET['estado']) && $_GET['estado'] == 'EN TRANSITO'): ?>
|
||||
<div class="d-flex justify-content-end my-3">
|
||||
<button id="verificar-estados-btn" class="btn btn-primary">
|
||||
<span class="spinner-border spinner-border-sm d-none" role="status" aria-hidden="true"></span>
|
||||
Verificar Estados
|
||||
</button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="table-responsive mt-4">
|
||||
<table class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Fecha</th>
|
||||
<th>Asesor</th>
|
||||
<th>Guía</th>
|
||||
<?php if (isset($_GET['estado']) && $_GET['estado'] == 'EN TRANSITO'): ?>
|
||||
<th style="width: 120px;">Estado Shalom</th>
|
||||
<?php endif; ?>
|
||||
<th>Cliente</th>
|
||||
<th>Celular</th>
|
||||
<th>Dirección</th>
|
||||
<th>Producto</th>
|
||||
<th>Total</th>
|
||||
<th>Estado</th>
|
||||
<th>Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if ($result && $result->rowCount() > 0): ?>
|
||||
<?php while ($row = $result->fetch(PDO::FETCH_ASSOC)): ?>
|
||||
<tr>
|
||||
<td><?php echo $row['id']; ?></td>
|
||||
<td><?php echo htmlspecialchars($row['fecha_pedido']); ?></td>
|
||||
<td><?php echo htmlspecialchars($row['asesor_nombre']); ?></td>
|
||||
<td><?php echo htmlspecialchars($row['guia']); ?></td>
|
||||
<?php if (isset($_GET['estado']) && $_GET['estado'] == 'EN TRANSITO'): ?>
|
||||
<td class="estado-shalom" data-id="<?php echo $row['id']; ?>" data-guia="<?php echo htmlspecialchars($row['guia']); ?>">
|
||||
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
||||
Verificando...
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
<td><?php echo htmlspecialchars($row['nombre_cliente']); ?></td>
|
||||
<td>
|
||||
<?php
|
||||
$celular_limpio = preg_replace('/[^0-9]/', '', $row['celular_cliente']);
|
||||
$whatsapp_icon_class = "fab fa-whatsapp text-secondary"; // Default grey icon
|
||||
$whatsapp_url = "#";
|
||||
$pointer_events = "none"; // Disable click by default
|
||||
|
||||
if (strlen($celular_limpio) > 8) {
|
||||
// The URL is prepared, but the link will be enabled via JS
|
||||
$mensaje_whatsapp = "¡Hola " . htmlspecialchars($row['nombre_cliente']) . "! Tu pedido ha llegado a la agencia de destino y está listo para ser recogido. ¡Gracias por tu compra!";
|
||||
$whatsapp_url = "https://wa.me/" . $celular_limpio . "?text=" . urlencode($mensaje_whatsapp);
|
||||
}
|
||||
?>
|
||||
<a href="<?php echo $whatsapp_url; ?>" target="_blank" class="whatsapp-link" data-id="<?php echo $row['id']; ?>" style="pointer-events: <?php echo $pointer_events; ?>;">
|
||||
<i class="<?php echo $whatsapp_icon_class; ?>"></i> <?php echo htmlspecialchars($row['celular_cliente']); ?>
|
||||
</a>
|
||||
</td>
|
||||
<td><?php echo htmlspecialchars($row['direccion_cliente']); ?></td>
|
||||
<td><?php echo htmlspecialchars($row['producto']); ?></td>
|
||||
<td>S/ <?php echo htmlspecialchars($row['total_pedido']); ?></td>
|
||||
<td><?php echo htmlspecialchars($row['estado']); ?></td>
|
||||
<td>
|
||||
<a href="pedido_form.php?edit=<?php echo $row['id']; ?>" class="btn btn-sm btn-info">Editar</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endwhile; ?>
|
||||
<?php else: ?>
|
||||
<tr>
|
||||
<td colspan="12" class="text-center">No se encontraron pedidos.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (isset($_GET['estado']) && $_GET['estado'] == 'EN TRANSITO'): ?>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const shalomApiUrl = 'shalom_api.php';
|
||||
|
||||
function verificarEstadoShalom(guia, id) {
|
||||
const estadoTd = document.querySelector(`.estado-shalom[data-id='${id}']`);
|
||||
const whatsappLink = document.querySelector(`.whatsapp-link[data-id='${id}']`);
|
||||
const whatsappIcon = whatsappLink ? whatsappLink.querySelector('i') : null;
|
||||
|
||||
if (!estadoTd) return;
|
||||
|
||||
return fetch(`${shalomApiUrl}?guia=${guia}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
estadoTd.innerHTML = `<span class="text-danger">Error</span>`;
|
||||
console.error('Error Shalom API:', data.error);
|
||||
} else {
|
||||
const estado = data.estado || 'No disponible';
|
||||
estadoTd.textContent = estado;
|
||||
|
||||
if (estado.includes('DESTINO') || estado.includes('ENTREGADO')) {
|
||||
estadoTd.classList.add('bg-success', 'text-white');
|
||||
if (whatsappIcon) {
|
||||
whatsappIcon.classList.remove('text-secondary');
|
||||
whatsappIcon.classList.add('text-success', 'fw-bold');
|
||||
whatsappLink.style.pointerEvents = 'auto';
|
||||
}
|
||||
} else {
|
||||
if (whatsappIcon) {
|
||||
whatsappIcon.classList.add('text-secondary');
|
||||
whatsappIcon.classList.remove('text-success', 'fw-bold');
|
||||
whatsappLink.style.pointerEvents = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
estadoTd.innerHTML = `<span class="text-danger">Fallo de red</span>`;
|
||||
console.error('Fetch error:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function actualizarTodosLosEstados() {
|
||||
const btn = document.getElementById('verificar-estados-btn');
|
||||
const spinner = btn.querySelector('.spinner-border');
|
||||
btn.disabled = true;
|
||||
spinner.classList.remove('d-none');
|
||||
|
||||
const promesas = [];
|
||||
document.querySelectorAll('.estado-shalom').forEach(td => {
|
||||
const guia = td.dataset.guia;
|
||||
const id = td.dataset.id;
|
||||
if (guia) {
|
||||
promesas.push(verificarEstadoShalom(guia, id));
|
||||
}
|
||||
});
|
||||
|
||||
Promise.all(promesas).finally(() => {
|
||||
btn.disabled = false;
|
||||
spinner.classList.add('d-none');
|
||||
});
|
||||
}
|
||||
|
||||
// Verificar todos al cargar la página
|
||||
actualizarTodosLosEstados();
|
||||
|
||||
// Verificar todos al hacer clic en el botón
|
||||
document.getElementById('verificar-estados-btn').addEventListener('click', function() {
|
||||
// Resetear estados visuales antes de verificar
|
||||
document.querySelectorAll('.estado-shalom').forEach(td => {
|
||||
td.innerHTML = `<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Verificando...`;
|
||||
td.classList.remove('bg-success', 'text-white');
|
||||
});
|
||||
document.querySelectorAll('.whatsapp-link').forEach(link => {
|
||||
const icon = link.querySelector('i');
|
||||
icon.classList.remove('text-success', 'fw-bold');
|
||||
icon.classList.add('text-secondary');
|
||||
link.style.pointerEvents = 'none';
|
||||
});
|
||||
actualizarTodosLosEstados();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<form method="GET" action="pedidos.php" class="row g-3 align-items-center">
|
||||
<div class="col-auto">
|
||||
<label for="q" class="form-label">Buscar</label>
|
||||
<input type="text" name="q" id="q" class="form-control" value="<?php echo htmlspecialchars($search_query); ?>" placeholder="Nombre, DNI o Celular">
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<label for="mes" class="form-label">Mes</label>
|
||||
<select name="mes" id="mes" class="form-select">
|
||||
<option value="">Todos</option>
|
||||
<?php foreach ($months as $num => $name): ?>
|
||||
<option value="<?php echo $num; ?>" <?php echo $selected_month == $num ? 'selected' : ''; ?>><?php echo $name; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<label for="año" class="form-label">Año</label>
|
||||
<select name="año" id="año" class="form-select">
|
||||
<option value="">Todos</option>
|
||||
<?php foreach ($years as $year): ?>
|
||||
<option value="<?php echo $year; ?>" <?php echo $selected_year == $year ? 'selected' : ''; ?>><?php echo $year; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-auto mt-4">
|
||||
<button type="submit" class="btn btn-info">Filtrar</button>
|
||||
<a href="pedidos.php" class="btn btn-secondary">Limpiar</a>
|
||||
<?php if ($user_role === 'Administrador'): ?>
|
||||
<a href="download_report.php" class="btn btn-success">Descargar Todos los Rotulados</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table id="pedidos-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Cliente</th>
|
||||
<th>DNI</th>
|
||||
<th>Celular</th>
|
||||
<th>Producto</th>
|
||||
<th>Sede de Envío</th>
|
||||
<th>Cantidad</th>
|
||||
<th>Monto Total</th>
|
||||
<th>Monto Debe</th>
|
||||
<th>Nº De Orden</th>
|
||||
<th>Codigo De Orden</th>
|
||||
<th>CLAVE</th>
|
||||
<th>Estado</th>
|
||||
<?php if ($user_role !== 'Asesor'): ?><th>Asesor</th><?php endif; ?>
|
||||
<th>Fecha Creación</th>
|
||||
<th>Voucher Restante</th>
|
||||
<th>Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($pedidos as $pedido): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($pedido['id']); ?></td>
|
||||
<td><?php echo htmlspecialchars($pedido['nombre_completo']); ?></td>
|
||||
<td><?php echo htmlspecialchars($pedido['dni_cliente'] ?? 'N/A'); ?></td>
|
||||
<td><?php echo htmlspecialchars($pedido['celular']); ?></td>
|
||||
<td><?php echo htmlspecialchars($pedido['producto']); ?></td>
|
||||
<td><?php echo htmlspecialchars($pedido['sede_envio'] ?? 'N/A'); ?></td>
|
||||
<td><?php echo htmlspecialchars($pedido['cantidad'] ?? '1'); ?></td>
|
||||
<td><?php echo htmlspecialchars($pedido['monto_total']); ?></td>
|
||||
<td><?php echo htmlspecialchars($pedido['monto_debe']); ?></td>
|
||||
<td class="editable" data-id="<?php echo $pedido['id']; ?>" data-field="codigo_rastreo"><?php echo htmlspecialchars($pedido['codigo_rastreo'] ?? 'N/A'); ?></td>
|
||||
<td class="editable" data-id="<?php echo $pedido['id']; ?>" data-field="codigo_tracking"><?php echo htmlspecialchars($pedido['codigo_tracking'] ?? 'N/A'); ?></td>
|
||||
<td class="editable" data-id="<?php echo $pedido['id']; ?>" data-field="clave"><?php echo htmlspecialchars($pedido['clave'] ?? 'N/A'); ?></td>
|
||||
<td><span class="badge" style="<?php echo getStatusStyle($pedido['estado']); ?>"><?php echo ($pedido['estado'] == 'Gestion') ? 'GESTIONES ⚙️' : htmlspecialchars($pedido['estado']); ?></span></td>
|
||||
<?php if ($user_role !== 'Asesor'): ?><td><?php echo htmlspecialchars($pedido['asesor_nombre'] ?? 'N/A'); ?></td><?php endif; ?>
|
||||
<td><?php echo htmlspecialchars($pedido['created_at']); ?></td>
|
||||
<td>
|
||||
<?php if (!empty($pedido['voucher_restante_path'])): ?>
|
||||
<a href="<?php echo htmlspecialchars($pedido['voucher_restante_path']); ?>" target="_blank">Ver</a>
|
||||
<?php else: ?>
|
||||
N/A
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
<a href="pedido_form.php?id=<?php echo $pedido['id']; ?>" class="btn btn-sm btn-warning">Editar</a>
|
||||
<?php if ($user_role === 'Administrador'): ?>
|
||||
<a href="delete_pedido.php?id=<?php echo $pedido['id']; ?>" class="btn btn-sm btn-danger" onclick="return confirm('¿Estás seguro de que quieres eliminar este pedido?');">Eliminar</a>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php if (empty($pedidos)): ?>
|
||||
<p class="text-center">No hay pedidos que coincidan con el filtro.</p>
|
||||
<?php endif; ?>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<?php include 'layout_footer.php'; ?>
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#pedidos-table').DataTable({
|
||||
"language": {
|
||||
"url": "//cdn.datatables.net/plug-ins/1.10.25/i18n/Spanish.json"
|
||||
},
|
||||
"order": [[ <?php echo ($user_role !== 'Asesor' ? 13 : 12); ?>, "desc" ]],
|
||||
"paging": false,
|
||||
"lengthChange": false,
|
||||
"info": false
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const table = document.querySelector('.table');
|
||||
|
||||
table.addEventListener('click', function(e) {
|
||||
if (e.target && e.target.classList.contains('editable')) {
|
||||
const cell = e.target;
|
||||
if (cell.querySelector('input')) {
|
||||
return; // Already in edit mode
|
||||
}
|
||||
|
||||
const originalContent = cell.textContent.trim();
|
||||
const input = document.createElement('input');
|
||||
input.type = 'text';
|
||||
input.className = 'form-control form-control-sm';
|
||||
input.value = originalContent === 'N/A' ? '' : originalContent;
|
||||
|
||||
cell.innerHTML = '';
|
||||
cell.appendChild(input);
|
||||
input.focus();
|
||||
|
||||
const saveChanges = function() {
|
||||
const newValue = input.value.trim();
|
||||
const pedidoId = cell.dataset.id;
|
||||
const field = cell.dataset.field;
|
||||
|
||||
let endpoint = 'update_tracking.php'; // Default endpoint
|
||||
if (field === 'clave') {
|
||||
endpoint = 'update_clave.php';
|
||||
}
|
||||
|
||||
// Restore original content visually
|
||||
cell.textContent = newValue === '' ? 'N/A' : newValue;
|
||||
|
||||
// Send data to server
|
||||
fetch(endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ id: pedidoId, field: field, value: newValue })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
console.error('Error:', data.error);
|
||||
// Optionally revert the change and show an error message
|
||||
cell.textContent = originalContent;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Fetch Error:', error);
|
||||
cell.textContent = originalContent;
|
||||
});
|
||||
};
|
||||
|
||||
input.addEventListener('blur', saveChanges);
|
||||
input.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
input.blur();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
193
test_pedidos.php
193
test_pedidos.php
@ -159,6 +159,7 @@ include 'layout_header.php';
|
||||
<div class="col-auto mt-4">
|
||||
<button type="submit" class="btn btn-info">Filtrar</button>
|
||||
<a href="test_pedidos.php" class="btn btn-secondary">Limpiar</a>
|
||||
<button type="button" id="verify-statuses-btn" class="btn btn-primary">Verificar Estados Ahora</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -183,6 +184,7 @@ include 'layout_header.php';
|
||||
<th>Codigo De Orden</th>
|
||||
<th>CLAVE</th>
|
||||
<th>Estado</th>
|
||||
<th>Estado Shalom</th>
|
||||
<?php if ($user_role !== 'Asesor'): ?><th>Asesor</th><?php endif; ?>
|
||||
<th>Fecha Creación</th>
|
||||
<th>Voucher Restante</th>
|
||||
@ -191,7 +193,7 @@ include 'layout_header.php';
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($pedidos as $pedido): ?>
|
||||
<tr>
|
||||
<tr id="pedido-<?php echo $pedido['id']; ?>" data-order-number="<?php echo htmlspecialchars($pedido['codigo_rastreo'] ?? ''); ?>" data-order-code="<?php echo htmlspecialchars($pedido['codigo_tracking'] ?? ''); ?>">
|
||||
<td><?php echo htmlspecialchars($pedido['id']); ?></td>
|
||||
<td><?php echo htmlspecialchars($pedido['nombre_completo']); ?></td>
|
||||
<td><?php echo htmlspecialchars($pedido['dni_cliente'] ?? 'N/A'); ?></td>
|
||||
@ -202,25 +204,23 @@ include 'layout_header.php';
|
||||
// Prepare WhatsApp message
|
||||
$nombre_cliente = $pedido['nombre_completo'];
|
||||
$producto = $pedido['producto'];
|
||||
// The user template has {CIUDAD} / {AGENCIA}, we'll use sede_envio for both.
|
||||
$sede_envio = $pedido['sede_envio'] ?? 'su agencia de destino';
|
||||
$monto_total = (float)($pedido['monto_total'] ?? 0);
|
||||
$monto_debe = (float)($pedido['monto_debe'] ?? 0);
|
||||
$adelanto = $monto_total - $monto_debe;
|
||||
|
||||
$template = "PLANTILLA – AVISO DE CLAVE DE RECOJO SHALOM\n\n"
|
||||
. "Estimado(a) {NOMBRE_CLIENTE} 👋\n"
|
||||
. "Le informamos que su pedido de {PRODUCTO} ya se encuentra disponible en su ciudad 📦\n\n"
|
||||
. "📍 Lugar de recojo: Shalom – {SEDE_ENVIO}\n\n"
|
||||
. "💰 Detalle de pago:\n"
|
||||
. "• Monto total del pedido: S/ {MONTO_TOTAL}\n"
|
||||
. "• Adelanto realizado: S/ {ADELANTO} ✅\n"
|
||||
. "• Saldo pendiente: S/ {SALDO_PENDIENTE}\n\n"
|
||||
. "Para continuar, le solicitamos enviar la captura de su pago restante por este medio 📄\n\n"
|
||||
. "Una vez confirmado su pago ✅, le enviaremos su clave de recojo 🔐, para que pueda retirar su pedido en la agencia sin inconvenientes 📦\n\n"
|
||||
. "Quedamos atentos a su confirmación.\n"
|
||||
. "Muchas gracias por su confianza 🤝\n\n"
|
||||
. "Floower Store 🛍️\n"
|
||||
$template = "Estimado(a) {NOMBRE_CLIENTE} 👋\n"
|
||||
. "Le informamos que su pedido de {PRODUCTO} ya se encuentra disponible en su ciudad 📦\n\n"
|
||||
. "📍 Lugar de recojo: Shalom – {SEDE_ENVIO}\n\n"
|
||||
. "💰 Detalle de pago:\n\n"
|
||||
. "• Monto total del pedido: S/ {MONTO_TOTAL}\n"
|
||||
. "• Adelanto realizado: S/ {ADELANTO} ✅\n"
|
||||
. "• Saldo pendiente: S/ {SALDO_PENDIENTE}\n\n"
|
||||
. "Para continuar, le solicitamos enviar la captura de su pago restante por este medio 📄\n\n"
|
||||
. "Una vez confirmado su pago ✅, le enviaremos su clave de recojo 🔐, para que pueda retirar su pedido en la agencia sin inconvenientes 📦\n\n"
|
||||
. "Quedamos atentos a su confirmación.\n"
|
||||
. "Muchas gracias por su confianza 🤝\n\n"
|
||||
. "Floower Store 🛍️\n"
|
||||
. "Área de Atención al Cliente";
|
||||
|
||||
$replacements = [
|
||||
@ -244,7 +244,7 @@ include 'layout_header.php';
|
||||
?>
|
||||
<div class="mt-1">
|
||||
<button type="button" class="btn btn-sm btn-info" title="Consultar Estado" data-bs-toggle="modal" data-bs-target="#trackingModal" data-order-number="<?php echo htmlspecialchars($pedido['codigo_rastreo'] ?? 'N/A'); ?>" data-order-code="<?php echo htmlspecialchars($pedido['codigo_tracking'] ?? 'N/A'); ?>">🔍</button>
|
||||
<a href="<?php echo $whatsappUrl; ?>" target="_blank" class="btn btn-sm btn-success" title="Enviar WhatsApp">💬</a>
|
||||
<a href="<?php echo $whatsappUrl; ?>" target="_blank" class="btn btn-sm btn-secondary whatsapp-icon" id="whatsapp-icon-<?php echo $pedido['id']; ?>" title="Enviar WhatsApp">💬</a>
|
||||
</div>
|
||||
</td>
|
||||
<td><?php echo htmlspecialchars($pedido['producto']); ?></td>
|
||||
@ -264,13 +264,14 @@ include 'layout_header.php';
|
||||
<td class="editable" data-id="<?php echo $pedido['id']; ?>" data-field="codigo_tracking"><?php echo htmlspecialchars($pedido['codigo_tracking'] ?? 'N/A'); ?></td>
|
||||
<td class="editable" data-id="<?php echo $pedido['id']; ?>" data-field="clave"><?php echo htmlspecialchars($pedido['clave'] ?? 'N/A'); ?></td>
|
||||
<td><span class="badge" style="<?php echo getStatusStyle($pedido['estado']); ?>"><?php echo ($pedido['estado'] == 'Gestion') ? 'GESTIONES ⚙️' : htmlspecialchars($pedido['estado']); ?></span></td>
|
||||
<td id="live-status-<?php echo $pedido['id']; ?>"><span class="badge bg-light text-dark">Pendiente</span></td>
|
||||
<?php if ($user_role !== 'Asesor'): ?><td><?php echo htmlspecialchars($pedido['asesor_nombre'] ?? 'N/A'); ?></td><?php endif; ?>
|
||||
<td><?php echo htmlspecialchars($pedido['created_at']); ?></td>
|
||||
<td>
|
||||
<?php if (!empty($pedido['voucher_restante_path'])): ?>
|
||||
<a href="<?php echo htmlspecialchars($pedido['voucher_restante_path']); ?>" target="_blank">Ver</a>
|
||||
<?php else: ?>
|
||||
N/A
|
||||
<?php else:
|
||||
?>N/A
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td>
|
||||
@ -295,12 +296,13 @@ include 'layout_header.php';
|
||||
<?php include 'layout_footer.php'; ?>
|
||||
|
||||
<script>
|
||||
// DataTable initialization and existing modal logic
|
||||
$(document).ready(function() {
|
||||
$('#pedidos-table').DataTable({
|
||||
$("#pedidos-table").DataTable({
|
||||
"language": {
|
||||
"url": "//cdn.datatables.net/plug-ins/1.10.25/i18n/Spanish.json"
|
||||
},
|
||||
"order": [[ <?php echo ($user_role !== 'Asesor' ? 13 : 12); ?>, "desc" ]],
|
||||
"order": [[ <?php echo ($user_role !== 'Asesor' ? 14 : 13); ?>, "desc" ]], // Adjusted index for new column
|
||||
"paging": false,
|
||||
"lengthChange": false,
|
||||
"info": false
|
||||
@ -317,7 +319,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
});
|
||||
|
||||
// Logic for tracking modal
|
||||
// Logic for tracking modal (existing logic)
|
||||
var trackingModal = document.getElementById('trackingModal');
|
||||
trackingModal.addEventListener('show.bs.modal', function (event) {
|
||||
var button = event.relatedTarget;
|
||||
@ -328,22 +330,18 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
var modalOrderCodeSpan = trackingModal.querySelector('#modal-order-code');
|
||||
var modalStatusDiv = trackingModal.querySelector('#modal-tracking-status');
|
||||
|
||||
// 1. Populate the modal with initial info
|
||||
modalOrderNumberSpan.textContent = orderNumber;
|
||||
modalOrderCodeSpan.textContent = orderCode;
|
||||
modalStatusDiv.innerHTML = '<p class="text-center">Consultando estado en Shalom...</p>';
|
||||
|
||||
// 2. Check if we have valid codes
|
||||
if (orderNumber === 'N/A' || orderCode === 'N/A' || !orderNumber || !orderCode) {
|
||||
modalStatusDiv.innerHTML = '<p class="text-danger text-center">No hay suficientes datos (Nº de Orden o Código de Orden) para consultar.</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Fetch the tracking status from our new API endpoint
|
||||
fetch(`shalom_api.php?orderNumber=${encodeURIComponent(orderNumber)}&orderCode=${encodeURIComponent(orderCode)}`)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
// Try to get error message from Shalom API response body
|
||||
return response.json().then(errorData => {
|
||||
throw new Error(errorData.error || `Error del servidor: ${response.status}`);
|
||||
});
|
||||
@ -351,7 +349,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
// 4. Display the result
|
||||
if (data.error) {
|
||||
modalStatusDiv.innerHTML = `<p class="text-danger text-center"><strong>Error:</strong> ${data.error}</p>`;
|
||||
} else if (data.search && data.search.success) {
|
||||
@ -359,48 +356,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const statusData = data.statuses.data;
|
||||
const statusMessage = data.statuses.message || 'No disponible';
|
||||
|
||||
let html = `
|
||||
<div class="alert alert-info text-center">
|
||||
<h5 class="alert-heading mb-0">Estado: ${statusMessage}</h5>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header"><strong>Origen</strong></div>
|
||||
<div class="card-body">
|
||||
<p class="card-text mb-1">${searchData.origen.nombre}</p>
|
||||
<p class="card-text mb-0"><small class="text-muted">${searchData.origen.direccion}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header"><strong>Destino</strong></div>
|
||||
<div class="card-body">
|
||||
<p class="card-text mb-1">${searchData.destino.nombre}</p>
|
||||
<p class="card-text mb-0"><small class="text-muted">${searchData.destino.direccion}</small></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="card-header"><strong>Detalles del Envío</strong></div>
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item"><strong>Remitente:</strong> ${searchData.remitente.nombre}</li>
|
||||
<li class="list-group-item"><strong>Destinatario:</strong> ${searchData.destinatario.nombre}</li>
|
||||
<li class="list-group-item"><strong>Fecha de Emisión:</strong> ${new Date(searchData.fecha_emision).toLocaleString('es-PE', { timeZone: 'America/Lima' })}</li>
|
||||
<li class="list-group-item"><strong>Contenido:</strong> ${searchData.contenido}</li>
|
||||
<li class="list-group-item"><strong>Monto a Pagar:</strong> S/ ${parseFloat(searchData.monto).toFixed(2)} (${searchData.tipo_pago})</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header"><strong>Historial de Estados</strong></div>
|
||||
<div class="card-body" style="font-size: 0.9rem;">
|
||||
`;
|
||||
|
||||
let html = `<div class="alert alert-info text-center"><h5 class="alert-heading mb-0">Estado: ${statusMessage}</h5></div>`;
|
||||
|
||||
const timeline = [
|
||||
{ name: 'Registrado', data: statusData.registrado },
|
||||
{ name: 'En Origen', data: statusData.origen },
|
||||
@ -409,7 +366,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
{ name: 'En Reparto', data: statusData.reparto },
|
||||
{ name: 'Entregado', data: statusData.entregado }
|
||||
];
|
||||
|
||||
html += '<div class="card mt-3"><div class="card-header"><strong>Historial de Estados</strong></div><div class="card-body" style="font-size: 0.9rem;">';
|
||||
timeline.forEach(item => {
|
||||
if (item.data && item.data.fecha) {
|
||||
html += `<p class="mb-1"><strong>${item.name}:</strong> <span class="text-success">${new Date(item.data.fecha).toLocaleString('es-PE', { timeZone: 'America/Lima' })}</span></p>`;
|
||||
@ -417,25 +374,99 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
html += `<p class="mb-1"><strong>${item.name}:</strong> <span class="text-muted">Pendiente</span></p>`;
|
||||
}
|
||||
});
|
||||
|
||||
html += `
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
||||
|
||||
|
||||
html += '</div></div>';
|
||||
modalStatusDiv.innerHTML = html;
|
||||
} else {
|
||||
modalStatusDiv.innerHTML = `<p class="text-warning text-center">No se pudo encontrar la guía o la respuesta no es válida.</p><pre><code>${JSON.stringify(data, null, 2)}</code></pre>`;
|
||||
modalStatusDiv.innerHTML = `<p class="text-warning text-center">No se pudo encontrar la guía.</p>`;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
// 5. Handle fetch or other errors
|
||||
console.error('Error fetching tracking status:', error);
|
||||
modalStatusDiv.innerHTML = `<p class="text-danger text-center"><strong>Error al consultar:</strong> ${error.message}</p>`;
|
||||
});
|
||||
});
|
||||
|
||||
// --- NEW ---
|
||||
function verificarEstados() {
|
||||
const rows = document.querySelectorAll('tr[data-order-number][data-order-code]');
|
||||
const verifyButton = document.getElementById('verify-statuses-btn');
|
||||
if(verifyButton) {
|
||||
verifyButton.disabled = true;
|
||||
verifyButton.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Verificando...';
|
||||
}
|
||||
|
||||
|
||||
rows.forEach((row, index) => {
|
||||
setTimeout(() => {
|
||||
const orderNumber = row.dataset.orderNumber;
|
||||
const orderCode = row.dataset.orderCode;
|
||||
const pedidoId = row.id.split('-')[1];
|
||||
const statusCell = document.getElementById(`live-status-${pedidoId}`);
|
||||
const whatsappIcon = document.getElementById(`whatsapp-icon-${pedidoId}`);
|
||||
|
||||
if (!statusCell) return;
|
||||
|
||||
if (!orderNumber || !orderCode || orderNumber === 'N/A' || orderCode === 'N/A') {
|
||||
statusCell.innerHTML = '<span class="badge bg-light text-dark">Sin datos</span>';
|
||||
return;
|
||||
}
|
||||
|
||||
statusCell.innerHTML = '<span class="badge bg-info text-dark">Verificando...</span>';
|
||||
|
||||
fetch(`shalom_api.php?orderNumber=${encodeURIComponent(orderNumber)}&orderCode=${encodeURIComponent(orderCode)}`)
|
||||
.then(response => {
|
||||
if (!response.ok) { throw new Error('Network response was not ok.'); }
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
statusCell.innerHTML = `<span class="badge bg-danger" title="${data.error}">Error</span>`;
|
||||
} else if (data.statuses && data.statuses.message) {
|
||||
const statusMessage = data.statuses.message;
|
||||
let badgeClass = 'bg-secondary';
|
||||
let whatsappClass = 'btn-secondary';
|
||||
|
||||
if (statusMessage.toUpperCase().includes('EN DESTINO')) {
|
||||
badgeClass = 'bg-success';
|
||||
whatsappClass = 'btn-success'; // Green
|
||||
} else if (statusMessage.toUpperCase().includes('EN TRANSITO')) {
|
||||
badgeClass = 'bg-primary';
|
||||
} else if (statusMessage.toUpperCase().includes('REGISTRADO')) {
|
||||
badgeClass = 'bg-warning text-dark';
|
||||
}
|
||||
|
||||
statusCell.innerHTML = `<span class="badge ${badgeClass}">${statusMessage}</span>`;
|
||||
|
||||
if (whatsappIcon) {
|
||||
whatsappIcon.classList.remove('btn-secondary', 'btn-success');
|
||||
whatsappIcon.classList.add(whatsappClass);
|
||||
}
|
||||
} else {
|
||||
statusCell.innerHTML = '<span class="badge bg-warning text-dark">Inválido</span>';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error fetching status:', error);
|
||||
statusCell.innerHTML = '<span class="badge bg-danger">Fallo</span>';
|
||||
})
|
||||
.finally(() => {
|
||||
// Re-enable button after the last request is done
|
||||
if (index === rows.length - 1 && verifyButton) {
|
||||
verifyButton.disabled = false;
|
||||
verifyButton.innerHTML = 'Verificar Estados Ahora';
|
||||
}
|
||||
});
|
||||
}, index * 500); // Stagger requests to avoid overwhelming the server/API
|
||||
});
|
||||
}
|
||||
|
||||
// Initial check on page load
|
||||
verificarEstados();
|
||||
|
||||
// Add event listener for the manual verification button
|
||||
const verifyButton = document.getElementById('verify-statuses-btn');
|
||||
if (verifyButton) {
|
||||
verifyButton.addEventListener('click', verificarEstados);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user