$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(); ensureTipoPaqueteEnumDefinition($pdo); $id = $_POST['id'] ?? null; $embed_mode = !empty($_POST['embed']) && $_POST['embed'] === '1'; $dni = trim($_POST['dni'] ?? ''); $nombre_completo = trim($_POST['nombre_completo'] ?? ''); $celular = trim($_POST['celular'] ?? ''); $agencia = trim($_POST['agencia'] ?? 'CONTRAENTREGA'); $provinciasPorDepartamentoContraentrega = contraentregaProvinciasPorDepartamento(); $distritosPorProvinciaContraentrega = contraentregaDistritosPorProvincia(); $departamentosContraentrega = array_keys($provinciasPorDepartamentoContraentrega); $sede_envio = trim($_POST['sede_envio'] ?? ''); $provincia = trim($_POST['provincia'] ?? ''); $distrito = trim($_POST['distrito'] ?? ''); $codigo_rastreo = trim($_POST['codigo_rastreo'] ?? ''); if ($provincia !== '' || $distrito !== '') { $codigo_rastreo = trim($provincia . ' / ' . $distrito, ' /'); } $codigo_tracking = trim($_POST['codigo_tracking'] ?? ''); $direccion_exacta = trim($_POST['direccion_exacta'] ?? ''); $referencia_domicilio = trim($_POST['referencia_domicilio'] ?? ''); $coordenadas = trim($_POST['coordenadas'] ?? ''); $seguimiento = trim($_POST['seguimiento'] ?? ''); $fecha_entrega_raw = trim((string)($_POST['fecha_entrega'] ?? '')); $fecha_entrega = null; if ($fecha_entrega_raw !== '' && $fecha_entrega_raw !== '0000-00-00') { if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $fecha_entrega_raw)) { redirectPedidoContraentregaWithError('La Fecha de Entrega no tiene un formato válido (YYYY-MM-DD).', $id, $embed_mode); } $fecha_entrega = $fecha_entrega_raw; } // --- Manejo de multiples productos --- $productos_post = $_POST['productos'] ?? []; $producto_nombres = []; $cantidad_total = 0; $productos_detalle = []; if (!empty($productos_post)) { foreach ($productos_post as $p) { if (!empty($p['nombre']) && !empty($p['cantidad'])) { $producto_nombres[] = trim($p['nombre']); $cantidad_total += (int)$p['cantidad']; $productos_detalle[] = trim($p['nombre']) . ' (x' . (int)$p['cantidad'] . ')'; } } } $producto = implode(', ', $producto_nombres); $cantidad = $cantidad_total; $notas_adicionales = "Detalle de productos: " . implode(', ', $productos_detalle); // --- Fin del manejo de multiples productos --- $monto_total = filter_var($_POST['monto_total'] ?? 0, FILTER_VALIDATE_FLOAT); $monto_adelantado = filter_var($_POST['monto_adelantado'] ?? 0, FILTER_VALIDATE_FLOAT); if ($monto_total === false) $monto_total = 0.0; if ($monto_adelantado === false) $monto_adelantado = 0.0; $numero_operacion = trim($_POST['numero_operacion'] ?? ''); $banco = trim($_POST['banco'] ?? ''); $notas = trim($_POST['notas'] ?? ''); $nota_adicional = trim($_POST['nota_adicional'] ?? ''); // Campo combinado del formulario: (Dedicatoria o grabado) + Observación del cliente // Guardamos en ambas columnas para mantener compatibilidad con el resto del sistema. $descargo = $nota_adicional; // Normalizar Paquete: el selector "Seleccionar" llega como cadena vacía, // pero la columna ENUM permite NULL y no permite ''. $tipo_paquete = normalizeTipoPaqueteValue($_POST['tipo_paquete'] ?? null); $tipos_paquete_validos = tipoPaqueteValidValues(); if ($tipo_paquete !== null && !in_array($tipo_paquete, $tipos_paquete_validos, true)) { redirectPedidoContraentregaWithError('El paquete seleccionado no es válido. Seleccione una opción de la lista.', $id, $embed_mode); } if (!empty($productos_detalle)) { $notas .= "\n\n" . $notas_adicionales; } if (!in_array($sede_envio, $departamentosContraentrega, true)) { redirectPedidoContraentregaWithError('Seleccione un departamento válido para el pedido contra entrega.', $id, $embed_mode); } if ($provincia !== '' && !in_array($provincia, $provinciasPorDepartamentoContraentrega[$sede_envio] ?? [], true)) { redirectPedidoContraentregaWithError('Seleccione una provincia válida para el departamento elegido.', $id, $embed_mode); } if ($distrito !== '' && isset($distritosPorProvinciaContraentrega[$provincia]) && !in_array($distrito, $distritosPorProvinciaContraentrega[$provincia], true)) { 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($fecha_entrega) || empty($coordenadas)) { redirectPedidoContraentregaWithError('Por favor, complete todos los campos obligatorios: fecha de entrega, 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) { redirectPedidoContraentregaWithError('El número de operación debe tener al menos 6 dígitos.', $id, $embed_mode); } // Check for duplicate operation number if (!empty($numero_operacion)) { $check_sql = "SELECT id FROM pedidos WHERE numero_operacion = ? AND id != ?"; $check_stmt = $pdo->prepare($check_sql); $check_stmt->execute([$numero_operacion, $id ?? 0]); $duplicate = $check_stmt->fetch(); if ($duplicate) { redirectPedidoContraentregaWithError('El número de operación ya existe en el pedido #' . $duplicate['id'], $id, $embed_mode); } } $monto_debe = $monto_total - $monto_adelantado; $params = [ 'dni_cliente' => $dni, 'nombre_completo' => $nombre_completo, 'celular' => $celular, 'agencia' => $agencia, 'sede_envio' => $sede_envio, 'direccion_exacta' => $direccion_exacta, 'referencia_domicilio' => $referencia_domicilio, 'coordenadas' => $coordenadas, 'codigo_rastreo' => $codigo_rastreo, 'codigo_tracking' => $codigo_tracking, 'producto' => $producto, 'cantidad' => $cantidad, 'monto_total' => $monto_total, 'monto_adelantado' => $monto_adelantado, 'numero_operacion' => $numero_operacion, 'banco' => $banco, 'monto_debe' => $monto_debe, 'notas' => $notas, 'nota_adicional' => $nota_adicional, 'descargo' => $descargo, 'seguimiento' => $seguimiento, 'fecha_entrega' => $fecha_entrega, 'tipo_paquete' => $tipo_paquete, ]; try { if ($id) { // UPDATE: Explicit and safe query $user_role = $_SESSION['user_role'] ?? ''; $sql_parts = [ "dni_cliente = :dni_cliente", "nombre_completo = :nombre_completo", "celular = :celular", "agencia = :agencia", "sede_envio = :sede_envio", "direccion_exacta = :direccion_exacta", "referencia_domicilio = :referencia_domicilio", "coordenadas = :coordenadas", "codigo_rastreo = :codigo_rastreo", "codigo_tracking = :codigo_tracking", "producto = :producto", "cantidad = :cantidad", "monto_total = :monto_total", "monto_adelantado = :monto_adelantado", "numero_operacion = :numero_operacion", "banco = :banco", "monto_debe = :monto_debe", "notas = :notas", "nota_adicional = :nota_adicional", "descargo = :descargo", "seguimiento = :seguimiento", "fecha_entrega = :fecha_entrega", "estado = :estado", "tipo_paquete = :tipo_paquete", ]; $params['estado'] = $_POST['estado'] ?? 'RUTA_CONTRAENTREGA'; // Conditionally add asesor_id if ($user_role === 'Administrador' && !empty($_POST['asesor_id'])) { $sql_parts[] = "asesor_id = :asesor_id"; $params['asesor_id'] = $_POST['asesor_id']; } $sql = "UPDATE pedidos SET " . implode(", ", $sql_parts) . " WHERE id = :id"; $params['id'] = $id; $stmt = $pdo->prepare($sql); $stmt->execute($params); } else { // INSERT: The advisor is the user creating the order. $params['asesor_id'] = $_SESSION['user_id']; $params['estado'] = $_POST['estado'] ?? 'RUTA_CONTRAENTREGA'; $columns_sql = "dni_cliente, nombre_completo, celular, agencia, sede_envio, direccion_exacta, referencia_domicilio, coordenadas, codigo_rastreo, codigo_tracking, producto, cantidad, monto_total, monto_adelantado, numero_operacion, banco, monto_debe, asesor_id, notas, nota_adicional, descargo, estado, seguimiento, fecha_entrega, tipo_paquete"; $values_sql = ":dni_cliente, :nombre_completo, :celular, :agencia, :sede_envio, :direccion_exacta, :referencia_domicilio, :coordenadas, :codigo_rastreo, :codigo_tracking, :producto, :cantidad, :monto_total, :monto_adelantado, :numero_operacion, :banco, :monto_debe, :asesor_id, :notas, :nota_adicional, :descargo, :estado, :seguimiento, :fecha_entrega, :tipo_paquete"; $sql = "INSERT INTO pedidos ($columns_sql) VALUES ($values_sql)"; $stmt = $pdo->prepare($sql); $stmt->execute($params); } } catch (PDOException $e) { die("Error en la base de datos: " . $e->getMessage()); } if (isset($_POST['id']) && !empty($_POST['id'])) { // Si se está editando un pedido, redirigir a la página de referencia o a la lista general. $redirect_url = $_POST['referer'] ?? 'pedidos_contraentrega.php'; } 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; } else { header('Location: pedidos_contraentrega.php'); exit; }