Autosave: 20260528-165045

This commit is contained in:
Flatlogic Bot 2026-05-28 16:50:41 +00:00
parent 93b3a0f69d
commit f244f447ec
4 changed files with 219 additions and 40 deletions

View File

@ -105,7 +105,7 @@ $navItems = [
'pedidos_rotulados_list' => [
'url' => 'pedidos.php',
'icon' => 'fa-clipboard-list',
'text' => 'Ver Pedidos Rotulados',
'text' => 'Pedidos Rotulados',
'roles' => ['Administrador', 'admin', 'Asesor', 'Control Logistico', 'Logistica']
],
'agregar_pedido' => [
@ -117,17 +117,24 @@ $navItems = [
]
],
'agregar_pedidos_contraentrega' => [
'url' => 'pedidos_contraentrega.php',
'icon' => 'fa-hand-holding-usd',
'text' => 'Agregar Pedidos Contraentrega',
'roles' => ['Administrador', 'admin', 'Asesor', 'Control Logistico', 'Soporte Logistico']
],
'ruta_contraentrega' => [
'url' => 'ruta_contraentrega.php',
'icon' => 'fa-route',
'text' => 'Ruta Contraentrega',
'roles' => ['Administrador', 'admin', 'Asesor', 'Control Logistico', 'Logistica', 'Soporte Logistico']
'roles' => ['Administrador', 'admin', 'Asesor', 'Control Logistico', 'Logistica', 'Soporte Logistico'],
'submenu' => [
'ruta_contraentrega_list' => [
'url' => 'ruta_contraentrega.php',
'icon' => 'fa-route',
'text' => 'Ruta Contraentrega',
'roles' => ['Administrador', 'admin', 'Asesor', 'Control Logistico', 'Logistica', 'Soporte Logistico']
],
'agregar_pedidos_contraentrega' => [
'url' => 'pedidos_contraentrega.php',
'icon' => 'fa-plus-circle',
'text' => 'Agregar Pedidos Contraentrega',
'roles' => ['Administrador', 'admin']
]
]
],
'inventario_group' => [
'icon' => 'fa-warehouse',

View File

@ -52,7 +52,7 @@ if (isset($_GET['id'])) {
}
} else {
// Security check: Only Administradors and asesores can create new pedidos
if ($user_role !== 'Administrador' && $user_role !== 'Asesor') {
if ($user_role !== 'Administrador' && $user_role !== 'admin' && $user_role !== 'Asesor') {
die('Acceso denegado. No tienes permiso para crear nuevos pedidos.');
}
}
@ -116,6 +116,14 @@ $pageTitle = 'Agregar Pedidos Contraentrega';
include 'layout_header.php';
?>
<?php if (($_GET['embed'] ?? '') === '1'): ?>
<style>
.sidebar, .sidebar-toggle { display: none !important; }
.content { margin-left: 0 !important; width: 100% !important; padding: 16px !important; }
.content .container-fluid > h1 { display: none !important; }
</style>
<?php endif; ?>
<?php if (isset($_GET['error'])):
$error_message = htmlspecialchars($_GET['error']);
?>
@ -129,6 +137,7 @@ include 'layout_header.php';
<form action="save_pedido_contraentrega.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="id" value="<?php echo htmlspecialchars($pedido['id']); ?>">
<input type="hidden" name="referer" value="<?php echo htmlspecialchars($_SERVER['HTTP_REFERER'] ?? 'pedidos.php'); ?>">
<input type="hidden" name="embed" value="<?php echo (($_GET['embed'] ?? '') === '1') ? '1' : '0'; ?>">
<!-- Asesor ID handling -->
<?php if ($user_role === 'Administrador'): ?>
@ -226,7 +235,8 @@ include 'layout_header.php';
</div>
<div class="col-md-6 mb-3">
<label for="coordenadas" class="form-label">Coordenadas</label>
<input type="text" class="form-control" id="coordenadas" name="coordenadas" value="<?php echo htmlspecialchars($pedido['coordenadas'] ?? ''); ?>" required>
<input type="text" class="form-control" id="coordenadas" name="coordenadas" value="<?php echo htmlspecialchars($pedido['coordenadas'] ?? ''); ?>" required inputmode="decimal" autocomplete="off" spellcheck="false" placeholder="-12.082029, -77.069024" pattern="-?[0-9]{1,2}\.[0-9]{6,}\s*,\s*-?[0-9]{1,3}\.[0-9]{6,}" title="Ingrese coordenadas válidas, por ejemplo: -12.082029, -77.069024">
<div class="form-text">Formato esperado: <strong>-12.082029, -77.069024</strong>. Solo números, coma, signo negativo y al menos 6 decimales por cada coordenada.</div>
</div>
</div>
@ -343,6 +353,63 @@ include 'layout_header.php';
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const pedidoForm = document.querySelector('form[action="save_pedido_contraentrega.php"]');
const coordenadasInput = document.getElementById('coordenadas');
if (!pedidoForm || !coordenadasInput) {
return;
}
const coordenadasRegex = /^\s*(-?\d{1,2}\.\d{6,})\s*,\s*(-?\d{1,3}\.\d{6,})\s*$/;
function validarCoordenadas() {
const value = coordenadasInput.value.trim();
if (value === '') {
coordenadasInput.setCustomValidity('Ingrese las coordenadas del pedido.');
return false;
}
const matches = value.match(coordenadasRegex);
if (!matches) {
coordenadasInput.setCustomValidity('Use el formato -12.082029, -77.069024, solo números y mínimo 6 decimales por valor.');
return false;
}
const latitud = parseFloat(matches[1]);
const longitud = parseFloat(matches[2]);
if (latitud < -90 || latitud > 90 || longitud < -180 || longitud > 180) {
coordenadasInput.setCustomValidity('Las coordenadas están fuera del rango permitido.');
return false;
}
coordenadasInput.setCustomValidity('');
return true;
}
coordenadasInput.addEventListener('input', function() {
const sanitizedValue = coordenadasInput.value.replace(/[^0-9,\.\-\s]/g, '');
if (sanitizedValue !== coordenadasInput.value) {
coordenadasInput.value = sanitizedValue;
}
validarCoordenadas();
});
coordenadasInput.addEventListener('blur', validarCoordenadas);
pedidoForm.addEventListener('submit', function(event) {
if (!validarCoordenadas()) {
event.preventDefault();
coordenadasInput.reportValidity();
coordenadasInput.focus();
}
});
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const provinciasPorDepartamento = <?php echo json_encode($provinciasPorDepartamentoContraentrega, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>;
@ -566,8 +633,25 @@ document.addEventListener('DOMContentLoaded', function() {
<script>
document.addEventListener('DOMContentLoaded', function() {
const urlParams = new URLSearchParams(window.location.search);
let inIframe = false;
try {
inIframe = window.self !== window.top;
} catch (e) {
inIframe = true;
}
if (urlParams.has('success')) {
alert('SE AGREGO CORRECTAMENTE ✅');
if (!inIframe) {
alert('SE AGREGO CORRECTAMENTE ✅');
} else {
try {
window.parent.postMessage({ type: "pedido_contraentrega_form_success" }, "*");
} catch (e) {
// ignore
}
}
// Remove the success parameter from the URL without reloading the page
const newUrl = window.location.pathname + window.location.hash;
window.history.replaceState({}, document.title, newUrl);

View File

@ -240,6 +240,11 @@ include 'layout_header.php';
<div class="col-auto mt-4">
<button type="submit" class="btn btn-info">Filtrar</button>
<a href="ruta_contraentrega.php" class="btn btn-secondary">Limpiar</a>
<?php if (in_array($user_role, ['Administrador', 'admin', 'Asesor'], true)): ?>
<button type="button" class="btn btn-primary ms-2" data-bs-toggle="modal" data-bs-target="#nuevoPedidoContraentregaModal">
AGREGAR PEDIDOS CONTRAENTREGA
</button>
<?php endif; ?>
<?php
$excelParams = array_filter([
'q' => $search_query,
@ -376,6 +381,68 @@ include 'layout_header.php';
<?php if (in_array($user_role, ['Administrador', 'admin', 'Asesor'], true)): ?>
<div class="modal fade" id="nuevoPedidoContraentregaModal" tabindex="-1" aria-labelledby="nuevoPedidoContraentregaModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable" style="max-width: 95vw;">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="nuevoPedidoContraentregaModalLabel">Agregar Pedidos Contraentrega</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cerrar"></button>
</div>
<div class="modal-body p-0">
<iframe id="nuevoPedidoContraentregaIframe" title="Formulario de pedidos contraentrega" src="about:blank" style="width:100%; height:90vh; border:0;"></iframe>
</div>
</div>
</div>
</div>
<?php endif; ?>
<script>
document.addEventListener('DOMContentLoaded', function() {
const nuevoPedidoModalEl = document.getElementById('nuevoPedidoContraentregaModal');
if (!nuevoPedidoModalEl) return;
const nuevoPedidoIframe = document.getElementById('nuevoPedidoContraentregaIframe');
let nuevoPedidoModalReloadGuard = false;
window.addEventListener('message', function(event) {
const data = event.data;
if (!data || typeof data !== 'object') return;
if (data.type === 'pedido_contraentrega_form_success') {
if (nuevoPedidoModalReloadGuard) return;
nuevoPedidoModalReloadGuard = true;
const modalInstance = bootstrap.Modal.getInstance(nuevoPedidoModalEl) || new bootstrap.Modal(nuevoPedidoModalEl);
modalInstance.hide();
window.location.reload();
}
});
nuevoPedidoModalEl.addEventListener('show.bs.modal', function() {
nuevoPedidoModalReloadGuard = false;
if (nuevoPedidoIframe) {
nuevoPedidoIframe.src = 'pedidos_contraentrega.php?embed=1&t=' + Date.now();
}
});
if (nuevoPedidoIframe) {
nuevoPedidoIframe.addEventListener('load', function() {
if (nuevoPedidoModalReloadGuard) return;
const src = nuevoPedidoIframe.src || '';
if (src.includes('success=1')) {
nuevoPedidoModalReloadGuard = true;
const modalInstance = bootstrap.Modal.getInstance(nuevoPedidoModalEl) || new bootstrap.Modal(nuevoPedidoModalEl);
modalInstance.hide();
window.location.reload();
}
});
}
});
</script>
<script>
function getPaqueteStyleJS(paquete) {
if (paquete === 'RUTA') return 'background-color: #0dcaf0; color: black;';

View File

@ -12,10 +12,43 @@ if (!isset($_SESSION['user_id'])) {
require_once 'db/config.php';
require_once __DIR__ . '/includes/contraentrega_cobertura.php';
function redirectPedidoContraentregaWithError(string $message, $id = null, bool $embed = false): void
{
$params = ['error' => $message];
if (!empty($id)) {
$params['id'] = $id;
}
if ($embed) {
$params['embed'] = '1';
}
header('Location: pedidos_contraentrega.php?' . http_build_query($params));
exit;
}
function normalizeContraentregaCoordinates(string $value): ?string
{
if (!preg_match('/^\s*(-?\d{1,2}\.\d{6,})\s*,\s*(-?\d{1,3}\.\d{6,})\s*$/', $value, $matches)) {
return null;
}
$latitud = (float) $matches[1];
$longitud = (float) $matches[2];
if ($latitud < -90 || $latitud > 90 || $longitud < -180 || $longitud > 180) {
return null;
}
return $matches[1] . ', ' . $matches[2];
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$pdo = db();
$id = $_POST['id'] ?? null;
$embed_mode = !empty($_POST['embed']) && $_POST['embed'] === '1';
$dni = trim($_POST['dni'] ?? '');
$nombre_completo = trim($_POST['nombre_completo'] ?? '');
@ -76,10 +109,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
$tipos_paquete_validos = ['RUTA', 'CONTRAENTREGA', 'NO CONTESTA, VOLVER A LLAMAR', 'PENDIENTE A RETORNO', 'COMPLETADO', 'RETORNADO', 'ANULADO'];
if ($tipo_paquete !== null && !in_array($tipo_paquete, $tipos_paquete_validos, true)) {
$error_message = urlencode('El paquete seleccionado no es válido. Seleccione una opción de la lista.');
$id_param = $id ? '&id=' . $id : '';
header('Location: pedidos_contraentrega.php?error=' . $error_message . $id_param);
exit;
redirectPedidoContraentregaWithError('El paquete seleccionado no es válido. Seleccione una opción de la lista.', $id, $embed_mode);
}
if (!empty($productos_detalle)) {
@ -87,39 +117,30 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if (!in_array($sede_envio, $departamentosContraentrega, true)) {
$error_message = urlencode('Seleccione un departamento válido para el pedido contra entrega.');
$id_param = $id ? '&id=' . $id : '';
header('Location: pedidos_contraentrega.php?error=' . $error_message . $id_param);
exit;
redirectPedidoContraentregaWithError('Seleccione un departamento válido para el pedido contra entrega.', $id, $embed_mode);
}
if ($provincia !== '' && !in_array($provincia, $provinciasPorDepartamentoContraentrega[$sede_envio] ?? [], true)) {
$error_message = urlencode('Seleccione una provincia válida para el departamento elegido.');
$id_param = $id ? '&id=' . $id : '';
header('Location: pedidos_contraentrega.php?error=' . $error_message . $id_param);
exit;
redirectPedidoContraentregaWithError('Seleccione una provincia válida para el departamento elegido.', $id, $embed_mode);
}
if ($distrito !== '' && isset($distritosPorProvinciaContraentrega[$provincia]) && !in_array($distrito, $distritosPorProvinciaContraentrega[$provincia], true)) {
$error_message = urlencode('Seleccione un distrito válido para la provincia elegida.');
$id_param = $id ? '&id=' . $id : '';
header('Location: pedidos_contraentrega.php?error=' . $error_message . $id_param);
exit;
redirectPedidoContraentregaWithError('Seleccione un distrito válido para la provincia elegida.', $id, $embed_mode);
}
if (empty($nombre_completo) || empty($celular) || empty($sede_envio) || empty($provincia) || empty($distrito) || empty($producto) || $cantidad === false || $monto_total === false || empty($coordenadas)) {
$error_message = urlencode('Por favor, complete todos los campos obligatorios: departamento, provincia, distrito y coordenadas.');
$id_param = $id ? '&id=' . $id : '';
header('Location: pedidos_contraentrega.php?error=' . $error_message . $id_param);
exit;
redirectPedidoContraentregaWithError('Por favor, complete todos los campos obligatorios: departamento, provincia, distrito y coordenadas.', $id, $embed_mode);
}
$coordenadasNormalizadas = normalizeContraentregaCoordinates($coordenadas);
if ($coordenadasNormalizadas === null) {
redirectPedidoContraentregaWithError('Ingrese coordenadas válidas con el formato -12.082029, -77.069024. No se aceptan letras ni coordenadas con pocos decimales.', $id, $embed_mode);
}
$coordenadas = $coordenadasNormalizadas;
// Check for minimum length of operation number
if (!empty($numero_operacion) && strlen($numero_operacion) < 6) {
$error_message = urlencode("El número de operación debe tener al menos 6 dígitos.");
$id_param = $id ? '&id=' . $id : '';
header('Location: pedidos_contraentrega.php?error=' . $error_message . $id_param);
exit;
redirectPedidoContraentregaWithError('El número de operación debe tener al menos 6 dígitos.', $id, $embed_mode);
}
// Check for duplicate operation number
@ -129,10 +150,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$check_stmt->execute([$numero_operacion, $id ?? 0]);
$duplicate = $check_stmt->fetch();
if ($duplicate) {
$error_message = urlencode("El número de operación ya existe en el pedido #" . $duplicate['id']);
$id_param = $id ? '&id=' . $id : '';
header('Location: pedidos_contraentrega.php?error=' . $error_message . $id_param);
exit;
redirectPedidoContraentregaWithError('El número de operación ya existe en el pedido #' . $duplicate['id'], $id, $embed_mode);
}
}
@ -226,6 +244,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
} else {
// Si se está creando un nuevo pedido, redirigir al formulario con un mensaje de éxito.
$redirect_url = 'pedidos_contraentrega.php?success=1';
if (!empty($_POST['embed']) && $_POST['embed'] === '1') {
$redirect_url .= '&embed=1';
}
}
header('Location: ' . $redirect_url);
exit;