Autosave: 20260505-022427

This commit is contained in:
Flatlogic Bot 2026-05-05 02:24:28 +00:00
parent 5b04629711
commit 5a30279f6c
62 changed files with 267 additions and 28 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 594 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 473 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 343 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@ -0,0 +1,2 @@
-- Migration: Add descargo column to pedidos table
ALTER TABLE pedidos ADD COLUMN descargo TEXT NULL;

View File

@ -10,11 +10,12 @@ try {
$pdo = db();
$type = $_GET['type'] ?? 'all';
// Filtramos solo los pedidos que están en estado 'ROTULADO 📦'
// Filtramos solo los pedidos que están en estado 'ROTULADO 📦' y son de la agencia 'SHALOM'
$query = "
SELECT p.dni_cliente, p.celular, p.sede_envio, p.agencia
FROM pedidos p
WHERE p.estado = 'ROTULADO 📦'
AND p.agencia LIKE '%SHALOM%'
";
if ($type === 'terrestre') {
@ -61,10 +62,22 @@ try {
foreach ($pedidos as $pedido) {
// Limpiar el DNI: solo números
$dni = preg_replace('/[^0-9]/', '', $pedido['dni_cliente'] ?? '');
$celular = htmlspecialchars($pedido['celular'] ?? '');
// Limpiar el celular: solo números
$celular = preg_replace('/[^0-9]/', '', $pedido['celular'] ?? '');
// Eliminar prefijo '51' si existe al inicio y el número es largo (ej. 51987654321)
if (str_starts_with($celular, '51') && strlen($celular) > 9) {
$celular = substr($celular, 2);
}
$celular = htmlspecialchars($celular);
$destino_raw = str_ireplace('shalom:', '', $pedido['sede_envio'] ?? '');
$parts = explode('/', $destino_raw);
$destino = trim(end($parts));
// Convertir a mayúsculas
$destino = mb_strtoupper($destino, 'UTF-8');
$destino = htmlspecialchars($destino);
$output .= '<tr>';

View File

@ -164,6 +164,7 @@ include 'layout_header.php';
<th> De Orden</th>
<th>Codigo De Orden</th>
<th>CLAVE</th>
<th>DESCARGO</th>
<th>PENDIENTES</th>
<th>Estado</th>
<?php if ($user_role !== 'Asesor'): ?><th>Asesor</th><?php endif; ?>
@ -193,6 +194,9 @@ include 'layout_header.php';
<td class="<?php echo $isEditableClave; ?>" data-id="<?php echo $pedido['id']; ?>" data-field="clave">
<?php echo $canSeeClave ? htmlspecialchars($pedido['clave'] ?? 'N/A') : '<i class="fas fa-eye-slash text-muted" title="Suba el número de operación y seleccione el banco para ver la clave"></i> <span class="text-muted" style="font-size: 0.8rem;">Oculto</span>'; ?>
</td>
<td class="editable" data-id="<?php echo $pedido['id']; ?>" data-field="descargo">
<?php echo htmlspecialchars($pedido['descargo'] ?? 'N/A'); ?>
</td>
<td class="editable-pendientes" data-id="<?php echo $pedido['id']; ?>" data-value="<?php echo htmlspecialchars($pedido['pendientes'] ?? ''); ?>" style="cursor: pointer;">
<span class="badge" style="<?php echo getPendientesStyle($pedido['pendientes'] ?? ''); ?>">
<?php echo htmlspecialchars(!empty($pedido['pendientes']) ? $pedido['pendientes'] : 'Seleccionar'); ?>
@ -325,13 +329,22 @@ document.addEventListener('DOMContentLoaded', function() {
if (e.target && e.target.classList.contains('editable')) {
const cell = e.target;
if (cell.querySelector('input')) {
if (cell.querySelector('input') || cell.querySelector('textarea')) {
return; // Already in edit mode
}
const originalContent = cell.textContent.trim();
const input = document.createElement('input');
input.type = 'text';
const field = cell.dataset.field;
let input;
if (field === 'descargo') {
input = document.createElement('textarea');
input.rows = 2;
} else {
input = document.createElement('input');
input.type = 'text';
}
input.className = 'form-control form-control-sm';
input.value = originalContent === 'N/A' ? '' : originalContent;
@ -347,6 +360,8 @@ document.addEventListener('DOMContentLoaded', function() {
let endpoint = 'update_tracking.php'; // Default endpoint
if (field === 'clave') {
endpoint = 'update_clave.php';
} else if (field === 'descargo') {
endpoint = 'update_pedido_field.php';
}
// Restore original content visually

View File

@ -226,6 +226,25 @@ $navItems = [
'text' => 'Gestionar Usuarios',
'roles' => ['Administrador', 'admin']
],
'marketing_group' => [
'icon' => 'fa-bullhorn',
'text' => 'Marketing',
'roles' => ['Administrador', 'admin'],
'submenu' => [
'marketing_produccion' => [
'url' => 'marketing_produccion.php',
'icon' => 'fa-video',
'text' => 'Producción de Video',
'roles' => ['Administrador', 'admin']
],
'marketing_assets' => [
'url' => 'marketing_assets.php',
'icon' => 'fa-folder-open',
'text' => 'Biblioteca de Assets',
'roles' => ['Administrador', 'admin']
],
]
],
'configuracion' => [
'url' => 'configuracion.php',
'icon' => 'fa-cog',

14
marketing_assets.php Normal file
View File

@ -0,0 +1,14 @@
<?php
$pageTitle = "Biblioteca de Assets";
include 'layout_header.php';
?>
<div class="card">
<div class="card-body">
<h5 class="card-title">Biblioteca de Recursos de Marketing</h5>
<p>Aquí podrás subir y organizar logos, intros de video, música y otros materiales que la editora deba utilizar de forma recurrente.</p>
<div class="alert alert-info">
<i class="bi bi-info-circle me-1"></i> Esta sección está en desarrollo. Pronto podrás gestionar tus archivos aquí.
</div>
</div>
</div>
<?php include 'layout_footer.php'; ?>

131
marketing_produccion.php Normal file
View File

@ -0,0 +1,131 @@
<?php
$pageTitle = "Producción de Video";
include 'db/config.php';
include 'layout_header.php';
$db = db();
// Obtener productos para el select
$stmt_products = $db->query("SELECT id, nombre FROM products ORDER BY nombre ASC");
$productos = $stmt_products->fetchAll(PDO::FETCH_ASSOC);
// Obtener videos existentes
$stmt_videos = $db->query("SELECT mv.*, p.nombre as nombre_producto
FROM marketing_videos mv
LEFT JOIN products p ON mv.producto_id = p.id
ORDER BY mv.fecha_creacion DESC");
$videos = $stmt_videos->fetchAll(PDO::FETCH_ASSOC);
?>
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>Gestión de Producción</h2>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#nuevoVideoModal">
<i class="fas fa-plus"></i> Nuevo Pedido de Video
</button>
</div>
<?php if (isset($_GET['success'])): ?>
<div class="alert alert-success alert-dismissible fade show" role="alert">
¡Pedido creado con éxito!
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php endif; ?>
<div class="row">
<?php if (empty($videos)): ?>
<div class="col-12 text-center py-5">
<i class="fas fa-video fa-4x text-muted mb-3"></i>
<p class="text-muted">No hay pedidos de video registrados aún.</p>
</div>
<?php else: ?>
<?php foreach ($videos as $v): ?>
<div class="col-md-4 mb-4">
<div class="card h-100 shadow-sm">
<div class="position-relative">
<?php if ($v['foto_producto']): ?>
<img src="<?php echo $v['foto_producto']; ?>" class="card-img-top" alt="Producto" style="height: 200px; object-fit: cover;">
<?php else: ?>
<div class="bg-light d-flex align-items-center justify-content-center" style="height: 200px;">
<i class="fas fa-image fa-3x text-muted"></i>
</div>
<?php endif; ?>
<span class="position-absolute top-0 end-0 m-2 badge <?php
echo $v['estado'] == 'Pendiente' ? 'bg-warning' :
($v['estado'] == 'En Proceso' ? 'bg-info' :
($v['estado'] == 'Terminado' ? 'bg-primary' : 'bg-success'));
?>">
<?php echo $v['estado']; ?>
</span>
</div>
<div class="card-body">
<h5 class="card-title"><?php echo htmlspecialchars($v['nombre_producto'] ?: 'Producto General'); ?></h5>
<p class="card-text text-muted small">
<?php echo nl2br(htmlspecialchars(substr($v['instrucciones'], 0, 100))); ?>...
</p>
<div class="d-flex justify-content-between align-items-center mt-3">
<small class="text-muted"><i class="far fa-calendar-alt"></i> <?php echo date('d/m/Y', strtotime($v['fecha_creacion'])); ?></small>
<?php if ($v['link_video']): ?>
<a href="<?php echo $v['link_video']; ?>" target="_blank" class="btn btn-sm btn-success">
<i class="fas fa-play"></i> Ver Video
</a>
<?php endif; ?>
</div>
</div>
<div class="card-footer bg-white border-top-0">
<button class="btn btn-outline-primary btn-sm w-100" onclick="verDetalles(<?php echo $v['id']; ?>)">
<i class="fas fa-edit"></i> Gestionar
</button>
</div>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<!-- Modal Nuevo Video -->
<div class="modal fade" id="nuevoVideoModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<form action="save_marketing_video.php" method="POST" enctype="multipart/form-data">
<div class="modal-header">
<h5 class="modal-title">Nuevo Pedido de Video</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label">Producto Relacionado</label>
<select name="producto_id" class="form-select">
<option value="">Seleccionar producto...</option>
<?php foreach ($productos as $p): ?>
<option value="<?php echo $p['id']; ?>"><?php echo htmlspecialchars($p['nombre']); ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label">Foto de Referencia / Ángulo</label>
<input type="file" name="foto_producto" class="form-control" accept="image/*">
</div>
<div class="col-12">
<label class="form-label">Instrucciones Detalladas</label>
<textarea name="instrucciones" class="form-control" rows="4" placeholder="Describe el ángulo, la música, el estilo del video, etc."></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
<button type="submit" class="btn btn-primary">Crear Pedido</button>
</div>
</form>
</div>
</div>
</div>
<script>
function verDetalles(id) {
// Por ahora solo mostramos un mensaje, luego implementaremos la edición
alert("Funcionalidad de edición para el ID " + id + " en desarrollo.");
}
</script>
<?php include 'layout_footer.php'; ?>

View File

@ -317,6 +317,11 @@ include 'layout_header.php';
<textarea class="form-control" id="observacion" name="observacion" rows="2"><?php echo htmlspecialchars($pedido['observacion'] ?? ''); ?></textarea>
</div>
<div class="mb-3">
<label for="descargo" class="form-label">Descargo (Observación del Cliente)</label>
<textarea class="form-control" id="descargo" name="descargo" rows="2"><?php echo htmlspecialchars($pedido['descargo'] ?? ''); ?></textarea>
</div>
<button type="submit" class="btn btn-primary">Guardar Pedido</button>
<a href="<?php echo htmlspecialchars($_SERVER['HTTP_REFERER'] ?? 'pedidos.php'); ?>" class="btn btn-secondary">Cancelar</a>
</form>

View File

@ -98,7 +98,7 @@ include 'layout_header.php';
<!-- Modal for tracking status -->
<div class="modal fade" id="trackingModal" tabindex="-1" aria-labelledby="trackingModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl" style="max-width: 950px;">
<div class="modal-dialog modal-xl" style="max-width: 1100px;">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="trackingModalLabel">Estado del Envío - Shalom</h5>
@ -416,23 +416,23 @@ document.addEventListener('DOMContentLoaded', function() {
const isCurrent = stepNum === activeStep;
stepsHtml += `
<div class="text-center" style="width: 100px; position: relative; z-index: 2;">
<div style="width: 32px; height: 32px; background-color: ${isActive ? '#e30613' : 'white'}; border: 2px solid ${isActive ? '#e30613' : '#fce4e4'}; border-radius: 50%; margin: 0 auto 10px; display: flex; align-items: center; justify-content: center;">
${isActive ? '<i class="fas fa-check" style="color: white; font-size: 16px;"></i>' : ''}
<div class="text-center" style="width: 120px; position: relative; z-index: 2;">
<div style="width: 36px; height: 36px; background-color: ${isActive ? '#e30613' : 'white'}; border: 2px solid ${isActive ? '#e30613' : '#fce4e4'}; border-radius: 50%; margin: 0 auto 10px; display: flex; align-items: center; justify-content: center;">
${isActive ? '<i class="fas fa-check" style="color: white; font-size: 18px;"></i>' : ''}
</div>
<span style="font-size: 1rem; font-weight: ${isCurrent ? 'bold' : 'normal'}; color: ${isActive ? '#1a1a6e' : '#999'}; display: block; white-space: nowrap;">${step}</span>
<span style="font-size: 1.1rem; font-weight: ${isCurrent ? 'bold' : 'normal'}; color: ${isActive ? '#1a1a6e' : '#999'}; display: block; white-space: nowrap;">${step}</span>
</div>
`;
});
let html = `
<div style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #333; background: white; padding: 40px 50px; border-radius: 15px; border: 1px solid #eee; box-shadow: 0 4px 12px rgba(0,0,0,0.05);">
<div style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; color: #333; background: white; padding: 50px 60px; border-radius: 15px; border: 1px solid #eee; box-shadow: 0 4px 12px rgba(0,0,0,0.05);">
<!-- Header Section -->
<div class="d-flex justify-content-between align-items-start mb-3 flex-wrap">
<div class="d-flex align-items-center mb-2">
<div class="me-4">
<!-- Illustration -->
<svg width="160" height="160" viewBox="0 0 200 200">
<svg width="180" height="180" viewBox="0 0 200 200">
<!-- Dashed path -->
<path d="M40 80C60 80 70 130 100 130C130 130 140 80 160 80" stroke="#94a3b8" stroke-width="3" stroke-dasharray="6 6" fill="none" />
@ -469,41 +469,41 @@ document.addEventListener('DOMContentLoaded', function() {
</div>
<div>
<div class="d-flex align-items-center mb-1">
<h1 style="color: #e30613 !important; font-weight: 900; margin: 0; margin-right: 15px; text-transform: uppercase; font-size: 2.8rem;">${statusMessage.toUpperCase()}</h1>
<span style="border: 3px solid #e30613; color: #e30613; border-radius: 25px; padding: 4px 15px; font-size: 1.1rem; font-weight: bold;">
<h1 style="color: #e30613 !important; font-weight: 900; margin: 0; margin-right: 15px; text-transform: uppercase; font-size: 3.2rem;">${statusMessage.toUpperCase()}</h1>
<span style="border: 3px solid #e30613; color: #e30613; border-radius: 25px; padding: 6px 20px; font-size: 1.2rem; font-weight: bold;">
<i class="fas fa-download"></i> GRT
</span>
</div>
<p class="mb-1" style="color: #666; font-size: 1.1rem;">${descriptionText}</p>
<p style="color: #e30613; font-weight: bold; font-size: 1rem; margin: 0;">
<p class="mb-1" style="color: #666; font-size: 1.3rem;">${descriptionText}</p>
<p style="color: #e30613; font-weight: bold; font-size: 1.1rem; margin: 0;">
<i class="fas fa-chevron-right"></i> Tiempo referencial de llegada 1 día.
</p>
</div>
</div>
<div class="text-sm-end">
<p class="mb-1" style="font-weight: bold; font-size: 1.1rem; color: #1a1a6e;"> DE ORDEN: ${orderNumber}</p>
<p class="text-muted" style="font-size: 1rem;">Desde el ${formattedDate}</p>
<p class="mb-1" style="font-weight: bold; font-size: 1.2rem; color: #1a1a6e;"> DE ORDEN: ${orderNumber}</p>
<p class="text-muted" style="font-size: 1.1rem;">Desde el ${formattedDate}</p>
</div>
</div>
<!-- Progress Bar -->
<div class="position-relative mb-4 mt-4" style="padding: 0 40px;">
<div class="progress" style="height: 10px; background-color: #fce4e4; border-radius: 5px;">
<div class="position-relative mb-5 mt-5" style="padding: 0 60px;">
<div class="progress" style="height: 12px; background-color: #fce4e4; border-radius: 6px;">
<div class="progress-bar" role="progressbar" style="width: ${progressWidth}%; background-color: #e30613;"></div>
</div>
<div class="d-flex justify-content-between position-absolute top-50 start-0 translate-middle-y w-100" style="padding: 0 20px;">
<div class="d-flex justify-content-between position-absolute top-50 start-0 translate-middle-y w-100" style="padding: 0 30px;">
${stepsHtml}
</div>
</div>
<!-- Footer Section -->
<div class="row mt-4 pt-4 border-top">
<div class="row mt-5 pt-4 border-top">
<div class="col-md-6 mb-2 mb-md-0">
<p class="mb-1" style="font-weight: bold; color: #1a1a6e; font-size: 1.1rem;">Origen: <span style="color: #888; font-weight: normal;">${searchData.origen.nombre || 'N/A'}</span></p>
<p class="mb-1" style="font-weight: bold; color: #1a1a6e; font-size: 1.2rem;">Origen: <span style="color: #888; font-weight: normal;">${searchData.origen.nombre || 'N/A'}</span></p>
</div>
<div class="col-md-6">
<p class="mb-1" style="font-weight: bold; color: #1a1a6e; font-size: 1.1rem;">Destino: <span style="color: #888; font-weight: normal;">${searchData.destino.nombre || 'N/A'}</span></p>
<p class="text-muted mb-0" style="font-size: 1rem;">${searchData.destino.direccion || ''}</p>
<p class="mb-1" style="font-weight: bold; color: #1a1a6e; font-size: 1.2rem;">Destino: <span style="color: #888; font-weight: normal;">${searchData.destino.nombre || 'N/A'}</span></p>
<p class="text-muted mb-0" style="font-size: 1.1rem;">${searchData.destino.direccion || ''}</p>
</div>
</div>
</div>

37
save_marketing_video.php Normal file
View File

@ -0,0 +1,37 @@
<?php
include 'db/config.php';
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit();
}
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$db = db();
$producto_id = !empty($_POST['producto_id']) ? $_POST['producto_id'] : null;
$instrucciones = $_POST['instrucciones'] ?? '';
$foto_path = null;
// Manejo de la subida de foto
if (isset($_FILES['foto_producto']) && $_FILES['foto_producto']['error'] == 0) {
$target_dir = "assets/uploads/marketing_images/";
$file_extension = pathinfo($_FILES["foto_producto"]["name"], PATHINFO_EXTENSION);
$file_name = uniqid() . '.' . $file_extension;
$target_file = $target_dir . $file_name;
if (move_uploaded_file($_FILES["foto_producto"]["tmp_name"], $target_file)) {
$foto_path = $target_file;
}
}
try {
$stmt = $db->prepare("INSERT INTO marketing_videos (producto_id, foto_producto, instrucciones, estado) VALUES (?, ?, ?, 'Pendiente')");
$stmt->execute([$producto_id, $foto_path, $instrucciones]);
header('Location: marketing_produccion.php?success=1');
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
}
?>

View File

@ -83,6 +83,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$estado = $_POST['estado'];
$notas = trim($_POST['notas']);
$observacion = trim($_POST['observacion'] ?? '');
$descargo = trim($_POST['descargo'] ?? '');
if (!empty($productos_detalle)) {
$notas .= "\n\n" . $notas_adicionales;
@ -153,6 +154,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
'estado' => $estado,
'notas' => $notas,
'observacion' => $observacion,
'descargo' => $descargo,
'voucher_adelanto_path' => $voucher_adelanto_path,
'voucher_restante_path' => $voucher_restante_path
];
@ -182,6 +184,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
"estado = :estado",
"notas = :notas",
"observacion = :observacion",
"descargo = :descargo",
"voucher_adelanto_path = :voucher_adelanto_path",
"voucher_restante_path = :voucher_restante_path"
];
@ -234,8 +237,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// INSERT: The advisor is the user creating the order.
$params['asesor_id'] = $_SESSION['user_id'];
$columns_sql = "dni_cliente, nombre_completo, celular, agencia, sede_envio, codigo_rastreo, codigo_tracking, clave, pendientes, producto, cantidad, monto_total, monto_adelantado, numero_operacion, banco, monto_debe, estado, asesor_id, notas, observacion, voucher_adelanto_path, voucher_restante_path";
$values_sql = ":dni_cliente, :nombre_completo, :celular, :agencia, :sede_envio, :codigo_rastreo, :codigo_tracking, :clave, :pendientes, :producto, :cantidad, :monto_total, :monto_adelantado, :numero_operacion, :banco, :monto_debe, :estado, :asesor_id, :notas, :observacion, :voucher_adelanto_path, :voucher_restante_path";
$columns_sql = "dni_cliente, nombre_completo, celular, agencia, sede_envio, codigo_rastreo, codigo_tracking, clave, pendientes, producto, cantidad, monto_total, monto_adelantado, numero_operacion, banco, monto_debe, estado, asesor_id, notas, observacion, descargo, voucher_adelanto_path, voucher_restante_path";
$values_sql = ":dni_cliente, :nombre_completo, :celular, :agencia, :sede_envio, :codigo_rastreo, :codigo_tracking, :clave, :pendientes, :producto, :cantidad, :monto_total, :monto_adelantado, :numero_operacion, :banco, :monto_debe, :estado, :asesor_id, :notas, :observacion, :descargo, :voucher_adelanto_path, :voucher_restante_path";
$completed_states = ['Completado', 'COMPLETADO ✅'];
if (in_array($estado, $completed_states)) {

View File

@ -21,7 +21,7 @@ $field = $data['field'];
$value = $data['value'];
// Whitelist allowed fields for security
$allowed_fields = ['numero_operacion', 'banco', 'clave', 'fecha_recojo', 'observacion'];
$allowed_fields = ['numero_operacion', 'banco', 'clave', 'fecha_recojo', 'observacion', 'descargo'];
if (!in_array($field, $allowed_fields)) {
http_response_code(400);
echo json_encode(['error' => 'Campo no permitido.']);