Autosave: 20260710-061850
This commit is contained in:
parent
3c0975c71c
commit
723db4cb01
@ -344,7 +344,7 @@ try {
|
|||||||
$aAgregado = !empty($a['is_agregado']);
|
$aAgregado = !empty($a['is_agregado']);
|
||||||
$bAgregado = !empty($b['is_agregado']);
|
$bAgregado = !empty($b['is_agregado']);
|
||||||
if ($aAgregado !== $bAgregado) {
|
if ($aAgregado !== $bAgregado) {
|
||||||
return $aAgregado ? 1 : -1;
|
return $aAgregado ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
$aImport = cc_test_import_time($a);
|
$aImport = cc_test_import_time($a);
|
||||||
@ -550,6 +550,7 @@ require_once 'layout_header.php';
|
|||||||
<div class="small"><strong>Departamento:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['sede'])); ?></div>
|
<div class="small"><strong>Departamento:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['sede'])); ?></div>
|
||||||
<div class="small"><strong>Provincia:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['ciudad'])); ?></div>
|
<div class="small"><strong>Provincia:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['ciudad'])); ?></div>
|
||||||
<div class="small"><strong>Distrito:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito'])); ?></div>
|
<div class="small"><strong>Distrito:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito'])); ?></div>
|
||||||
|
<div class="small"><strong>Coordenadas:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['coordenadas'], 'Sin coordenadas')); ?></div>
|
||||||
<?php if (!empty(trim((string) ($order['distrito_drive'] ?? '')))): ?>
|
<?php if (!empty(trim((string) ($order['distrito_drive'] ?? '')))): ?>
|
||||||
<div class="small"><strong>DISTRITO 1:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito_drive'])); ?></div>
|
<div class="small"><strong>DISTRITO 1:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito_drive'])); ?></div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -575,6 +576,9 @@ require_once 'layout_header.php';
|
|||||||
<?php if (!empty($order['fecha_entrega_programada'])): ?>
|
<?php if (!empty($order['fecha_entrega_programada'])): ?>
|
||||||
<div class="small text-muted">Entrega programada: <?php echo htmlspecialchars(cc_test_format_date($order['fecha_entrega_programada'] ?? null)); ?></div>
|
<div class="small text-muted">Entrega programada: <?php echo htmlspecialchars(cc_test_format_date($order['fecha_entrega_programada'] ?? null)); ?></div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<?php if (!empty($order['ruta_contraentrega_pedido_id'])): ?>
|
||||||
|
<div class="small text-success">Subido a Ruta Contraentrega #<?php echo (int) $order['ruta_contraentrega_pedido_id']; ?><?php if (!empty($order['ruta_contraentrega_subido_at'])): ?> · <?php echo htmlspecialchars(cc_test_format_datetime($order['ruta_contraentrega_subido_at'] ?? null, '')); ?><?php endif; ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
<div class="small text-muted">Última gestión: <?php echo htmlspecialchars(cc_test_format_datetime($order['ultima_gestion_at'] ?? ($order['seguimiento_actualizado'] ?? null), 'Aún no gestionado')); ?></div>
|
<div class="small text-muted">Última gestión: <?php echo htmlspecialchars(cc_test_format_datetime($order['ultima_gestion_at'] ?? ($order['seguimiento_actualizado'] ?? null), 'Aún no gestionado')); ?></div>
|
||||||
<div class="small text-muted mt-1">Nota: <?php echo htmlspecialchars(cc_test_display_value($order['nota_seguimiento'], 'Sin nota interna')); ?></div>
|
<div class="small text-muted mt-1">Nota: <?php echo htmlspecialchars(cc_test_display_value($order['nota_seguimiento'], 'Sin nota interna')); ?></div>
|
||||||
</td>
|
</td>
|
||||||
@ -677,13 +681,27 @@ require_once 'layout_header.php';
|
|||||||
<div class="modal fade" id="<?php echo htmlspecialchars($modalId); ?>" tabindex="-1" aria-hidden="true">
|
<div class="modal fade" id="<?php echo htmlspecialchars($modalId); ?>" tabindex="-1" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header align-items-start gap-2">
|
||||||
<div>
|
<div class="flex-grow-1 min-w-0">
|
||||||
<div class="small text-primary fw-semibold mb-1"><?php echo htmlspecialchars(cc_test_order_label($order)); ?></div>
|
<div class="small text-primary fw-semibold mb-1"><?php echo htmlspecialchars(cc_test_order_label($order)); ?></div>
|
||||||
<h3 class="modal-title h5 mb-1"><?php echo htmlspecialchars(cc_test_display_value($order['nombre'], 'Cliente sin nombre')); ?></h3>
|
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2">
|
||||||
<div class="small text-muted"><?php echo htmlspecialchars(cc_test_display_value($order['producto'], 'Sin producto')); ?> · <?php echo htmlspecialchars(cc_test_display_value($order['celular'], 'Sin celular')); ?></div>
|
<h3 class="modal-title h5 mb-0"><?php echo htmlspecialchars(cc_test_display_value($order['nombre'], 'Cliente sin nombre')); ?></h3>
|
||||||
|
<?php if ($storeKey === 'otra_tienda'): ?>
|
||||||
|
<button type="button" class="btn btn-primary btn-sm px-3" id="subir-ruta-<?php echo htmlspecialchars($order['source_key']); ?>" onclick="guardarGestion('<?php echo htmlspecialchars($order['source_key']); ?>', this, { subirRuta: true })"><?php echo !empty($order['ruta_contraentrega_pedido_id']) ? 'Actualizar en ruta' : 'Subir pedido'; ?></button>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<div class="small text-muted mt-1"><?php echo htmlspecialchars(cc_test_display_value($order['producto'], 'Sin producto')); ?> · <?php echo htmlspecialchars(cc_test_display_value($order['celular'], 'Sin celular')); ?></div>
|
||||||
|
<?php if ($storeKey === 'otra_tienda'): ?>
|
||||||
|
<div class="small mt-2 <?php echo !empty($order['ruta_contraentrega_pedido_id']) ? 'text-success fw-semibold' : 'text-muted'; ?>">
|
||||||
|
<?php if (!empty($order['ruta_contraentrega_pedido_id'])): ?>
|
||||||
|
En Ruta Contraentrega #<?php echo (int) $order['ruta_contraentrega_pedido_id']; ?>. Si cambias algo, usa este botón para actualizarlo.
|
||||||
|
<?php else: ?>
|
||||||
|
Súbelo cuando quede en <strong>CONFIRMADO CONTRAENTREGA</strong>.
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cerrar"></button>
|
<button type="button" class="btn-close mt-1" data-bs-dismiss="modal" aria-label="Cerrar"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="border border-primary-subtle rounded-4 bg-primary-subtle p-2 mb-3" id="airDroidModalCard-<?php echo htmlspecialchars($order['source_key']); ?>">
|
<div class="border border-primary-subtle rounded-4 bg-primary-subtle p-2 mb-3" id="airDroidModalCard-<?php echo htmlspecialchars($order['source_key']); ?>">
|
||||||
@ -700,6 +718,7 @@ require_once 'layout_header.php';
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="border border-success-subtle rounded-4 bg-white p-3 mb-4 shadow-sm cc-readonly-block" aria-disabled="true" style="user-select:none; -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none;">
|
<div class="border border-success-subtle rounded-4 bg-white p-3 mb-4 shadow-sm cc-readonly-block" aria-disabled="true" style="user-select:none; -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none;">
|
||||||
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-3">
|
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-3">
|
||||||
<div>
|
<div>
|
||||||
@ -840,8 +859,8 @@ require_once 'layout_header.php';
|
|||||||
<div class="form-text">Úsalo cuando el cliente quede en Confirmado fecha.</div>
|
<div class="form-text">Úsalo cuando el cliente quede en Confirmado fecha.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<label for="nota-<?php echo htmlspecialchars($order['source_key']); ?>" class="form-label">Nota interna</label>
|
<label for="nota-<?php echo htmlspecialchars($order['source_key']); ?>" class="form-label">COLOCAR AQUI OBSERVACION DEL CLIENTE O (DEDICATORIA O GRABADO)</label>
|
||||||
<textarea class="form-control" id="nota-<?php echo htmlspecialchars($order['source_key']); ?>" rows="3" placeholder="Ejemplo: cliente pidió volver a llamar después de las 5 pm."><?php echo htmlspecialchars($order['nota_seguimiento']); ?></textarea>
|
<textarea class="form-control" id="nota-<?php echo htmlspecialchars($order['source_key']); ?>" rows="3" placeholder="Ej.: Solicita dedicatoria para hija María, Ej.: Desea antes de las 4PM"><?php echo htmlspecialchars($order['nota_seguimiento']); ?></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -910,6 +929,11 @@ require_once 'layout_header.php';
|
|||||||
<input type="hidden" id="distrito-<?php echo htmlspecialchars($order['source_key']); ?>" value="<?php echo htmlspecialchars($distritoSeleccionado); ?>">
|
<input type="hidden" id="distrito-<?php echo htmlspecialchars($order['source_key']); ?>" value="<?php echo htmlspecialchars($distritoSeleccionado); ?>">
|
||||||
<div class="form-text">Si la provincia aún no tiene cobertura cargada, podrás escribir el distrito manualmente.</div>
|
<div class="form-text">Si la provincia aún no tiene cobertura cargada, podrás escribir el distrito manualmente.</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="coordenadas-<?php echo htmlspecialchars($order['source_key']); ?>" class="form-label">Coordenadas</label>
|
||||||
|
<input type="text" class="form-control" id="coordenadas-<?php echo htmlspecialchars($order['source_key']); ?>" value="<?php echo htmlspecialchars((string) ($order['coordenadas'] ?? '')); ?>" inputmode="decimal" autocomplete="off" spellcheck="false" placeholder="-12.082029, -77.069024">
|
||||||
|
<div class="form-text">Obligatorias para <strong>Subir pedido</strong> a Ruta Contraentrega.</div>
|
||||||
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="agencia-<?php echo htmlspecialchars($order['source_key']); ?>" class="form-label">Agencia</label>
|
<label for="agencia-<?php echo htmlspecialchars($order['source_key']); ?>" class="form-label">Agencia</label>
|
||||||
<select class="form-select" id="agencia-<?php echo htmlspecialchars($order['source_key']); ?>">
|
<select class="form-select" id="agencia-<?php echo htmlspecialchars($order['source_key']); ?>">
|
||||||
@ -948,7 +972,8 @@ require_once 'layout_header.php';
|
|||||||
<div class="mb-1"><strong>Referencia Drive:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['referencia_drive'] ?? null)); ?></div>
|
<div class="mb-1"><strong>Referencia Drive:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['referencia_drive'] ?? null)); ?></div>
|
||||||
<div class="mb-1"><strong>Distrito 1:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito_drive'] ?? null)); ?></div>
|
<div class="mb-1"><strong>Distrito 1:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito_drive'] ?? null)); ?></div>
|
||||||
<div class="mb-1"><strong>Distrito:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito'] ?? null)); ?></div>
|
<div class="mb-1"><strong>Distrito:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito'] ?? null)); ?></div>
|
||||||
<div><strong>Observación Drive:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['observaciones_drive'] ?? null)); ?></div>
|
<div class="mb-1"><strong>Observación Drive:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['observaciones_drive'] ?? null)); ?></div>
|
||||||
|
<div><strong>Coordenadas Drive:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['coordenadas_drive'] ?? null)); ?></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4 class="h6 fw-bold mb-3">Historial de llamadas</h4>
|
<h4 class="h6 fw-bold mb-3">Historial de llamadas</h4>
|
||||||
@ -973,9 +998,16 @@ require_once 'layout_header.php';
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer d-flex justify-content-between">
|
|
||||||
<div class="small text-muted">Los cambios se guardan en la base local del módulo de prueba.</div>
|
<div class="modal-footer d-flex justify-content-between flex-wrap gap-2">
|
||||||
<div class="d-flex gap-2">
|
<div class="small text-muted">
|
||||||
|
<?php if ($storeKey === 'otra_tienda'): ?>
|
||||||
|
<strong>Guardar gestión</strong> solo guarda el historial. Para enviarlo a logística, usa <strong>Subir pedido</strong> junto al nombre del cliente.
|
||||||
|
<?php else: ?>
|
||||||
|
Los cambios se guardan en la base local del módulo de prueba.
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex gap-2 ms-auto">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
|
||||||
<button type="button" class="btn btn-primary" onclick="guardarGestion('<?php echo htmlspecialchars($order['source_key']); ?>', this)">Guardar gestión</button>
|
<button type="button" class="btn btn-primary" onclick="guardarGestion('<?php echo htmlspecialchars($order['source_key']); ?>', this)">Guardar gestión</button>
|
||||||
</div>
|
</div>
|
||||||
@ -1153,6 +1185,7 @@ function toggleAgendaFields(sourceKey) {
|
|||||||
const deliveryGroup = document.getElementById('delivery-group-' + sourceKey);
|
const deliveryGroup = document.getElementById('delivery-group-' + sourceKey);
|
||||||
const nextCallInput = document.getElementById('proxima-' + sourceKey);
|
const nextCallInput = document.getElementById('proxima-' + sourceKey);
|
||||||
const deliveryInput = document.getElementById('fecha-entrega-' + sourceKey);
|
const deliveryInput = document.getElementById('fecha-entrega-' + sourceKey);
|
||||||
|
const routeButton = document.getElementById('subir-ruta-' + sourceKey);
|
||||||
const needsDeliveryDate = estado === 'CONFIRMADO CONTRAENTREGA';
|
const needsDeliveryDate = estado === 'CONFIRMADO CONTRAENTREGA';
|
||||||
const needsNextCall = ['POR LLAMAR', 'DEVOLVER LLAMADA', 'OBSERVADO'].includes(estado);
|
const needsNextCall = ['POR LLAMAR', 'DEVOLVER LLAMADA', 'OBSERVADO'].includes(estado);
|
||||||
|
|
||||||
@ -1168,6 +1201,9 @@ function toggleAgendaFields(sourceKey) {
|
|||||||
if (!needsDeliveryDate && deliveryInput) {
|
if (!needsDeliveryDate && deliveryInput) {
|
||||||
deliveryInput.value = '';
|
deliveryInput.value = '';
|
||||||
}
|
}
|
||||||
|
if (routeButton) {
|
||||||
|
routeButton.disabled = !needsDeliveryDate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
@ -1259,7 +1295,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function guardarGestion(sourceKey, trigger) {
|
function guardarGestion(sourceKey, trigger, options = {}) {
|
||||||
|
const subirRuta = options.subirRuta === true;
|
||||||
const body = new URLSearchParams({
|
const body = new URLSearchParams({
|
||||||
source_key: sourceKey,
|
source_key: sourceKey,
|
||||||
estado: document.getElementById('estado-' + sourceKey)?.value || 'POR LLAMAR',
|
estado: document.getElementById('estado-' + sourceKey)?.value || 'POR LLAMAR',
|
||||||
@ -1273,6 +1310,7 @@ function guardarGestion(sourceKey, trigger) {
|
|||||||
sede: document.getElementById('sede-' + sourceKey)?.value || '',
|
sede: document.getElementById('sede-' + sourceKey)?.value || '',
|
||||||
ciudad: document.getElementById('ciudad-' + sourceKey)?.value || '',
|
ciudad: document.getElementById('ciudad-' + sourceKey)?.value || '',
|
||||||
distrito: document.getElementById('distrito-' + sourceKey)?.value || '',
|
distrito: document.getElementById('distrito-' + sourceKey)?.value || '',
|
||||||
|
coordenadas: document.getElementById('coordenadas-' + sourceKey)?.value || '',
|
||||||
dni: document.getElementById('dni-' + sourceKey)?.value || '',
|
dni: document.getElementById('dni-' + sourceKey)?.value || '',
|
||||||
observaciones: document.getElementById('observaciones-' + sourceKey)?.value || '',
|
observaciones: document.getElementById('observaciones-' + sourceKey)?.value || '',
|
||||||
producto: document.getElementById('producto-' + sourceKey)?.value || '',
|
producto: document.getElementById('producto-' + sourceKey)?.value || '',
|
||||||
@ -1283,7 +1321,8 @@ function guardarGestion(sourceKey, trigger) {
|
|||||||
confirmacion_precio: document.getElementById('confirmacion_precio-' + sourceKey)?.value || '',
|
confirmacion_precio: document.getElementById('confirmacion_precio-' + sourceKey)?.value || '',
|
||||||
confirmacion_producto_extra: document.getElementById('confirmacion_producto_extra-' + sourceKey)?.value || '',
|
confirmacion_producto_extra: document.getElementById('confirmacion_producto_extra-' + sourceKey)?.value || '',
|
||||||
confirmacion_cantidad_extra: document.getElementById('confirmacion_cantidad_extra-' + sourceKey)?.value || '',
|
confirmacion_cantidad_extra: document.getElementById('confirmacion_cantidad_extra-' + sourceKey)?.value || '',
|
||||||
confirmacion_precio_extra: document.getElementById('confirmacion_precio_extra-' + sourceKey)?.value || ''
|
confirmacion_precio_extra: document.getElementById('confirmacion_precio_extra-' + sourceKey)?.value || '',
|
||||||
|
subir_a_ruta: subirRuta ? '1' : '0'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (trigger) {
|
if (trigger) {
|
||||||
@ -1300,6 +1339,9 @@ function guardarGestion(sourceKey, trigger) {
|
|||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
throw new Error(data.message || 'No se pudo guardar la gestión');
|
throw new Error(data.message || 'No se pudo guardar la gestión');
|
||||||
}
|
}
|
||||||
|
if (subirRuta) {
|
||||||
|
alert(data.message || 'Pedido subido a Ruta Contraentrega correctamente.');
|
||||||
|
}
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|||||||
@ -1,54 +1,53 @@
|
|||||||
<?php
|
<?php
|
||||||
session_start();
|
session_start();
|
||||||
|
|
||||||
if (!isset($_SESSION['user_id'])) {
|
if (!isset($_SESSION["user_id"])) {
|
||||||
header('Location: login.php');
|
header("Location: login.php");
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once 'db/config.php';
|
require_once "vendor/autoload.php";
|
||||||
require_once 'vendor/autoload.php';
|
|
||||||
|
|
||||||
use Shuchkin\SimpleXLSXGen;
|
use Shuchkin\SimpleXLSXGen;
|
||||||
|
|
||||||
$headers = [
|
$headers = [
|
||||||
'NOMBRE',
|
"NOMBRE",
|
||||||
'CELULAR',
|
"DIRECION",
|
||||||
'DNI',
|
"REFERENCIA",
|
||||||
'DIRECCION',
|
"DISTRITO",
|
||||||
'REFERENCIA',
|
"CELULAR",
|
||||||
'SEDE',
|
"PRODUCTO",
|
||||||
'CIUDAD',
|
"CANTIDAD",
|
||||||
'DISTRITO',
|
"PRECIO",
|
||||||
'PRODUCTO',
|
"PAIS",
|
||||||
'CANTIDAD',
|
"COORDENADAS",
|
||||||
'PRECIO',
|
"CIUDAD",
|
||||||
'PAIS',
|
"METODO",
|
||||||
'COORDENADAS',
|
"SEDE / ID",
|
||||||
'METODO',
|
"N° DNI",
|
||||||
'OBSERVACIONES'
|
"OBSERVACIONES"
|
||||||
];
|
];
|
||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
$headers,
|
$headers,
|
||||||
[
|
[
|
||||||
'Ej: Juan Pérez',
|
"Ej: Juan Pérez",
|
||||||
'999999999',
|
"Av. Siempre Viva 123",
|
||||||
'12345678',
|
"Referencia (opcional)",
|
||||||
'Av. Siempre Viva 123',
|
"Distrito",
|
||||||
'Referencia (opcional)',
|
"999999999",
|
||||||
'Sede / ID',
|
"Producto",
|
||||||
'Ciudad',
|
"1",
|
||||||
'Distrito',
|
"10.50",
|
||||||
'Producto',
|
"Perú",
|
||||||
'1',
|
"lat,long",
|
||||||
'10.50',
|
"Ciudad",
|
||||||
'Perú',
|
"Contraentrega",
|
||||||
'lat,long',
|
"Sede / ID",
|
||||||
'Contraentrega',
|
"12345678",
|
||||||
'Observaciones (opcional)'
|
"Observaciones (opcional)"
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
$filename = 'plantilla_agregados_pedidos.xlsx';
|
$filename = "plantilla_agregados_pedidos.xlsx";
|
||||||
SimpleXLSXGen::fromArray($data, 'Agregados')->downloadAs($filename);
|
SimpleXLSXGen::fromArray($data, "Agregados")->downloadAs($filename);
|
||||||
|
|||||||
@ -543,7 +543,7 @@ try {
|
|||||||
$aAgregado = !empty($a['is_agregado']);
|
$aAgregado = !empty($a['is_agregado']);
|
||||||
$bAgregado = !empty($b['is_agregado']);
|
$bAgregado = !empty($b['is_agregado']);
|
||||||
if ($aAgregado !== $bAgregado) {
|
if ($aAgregado !== $bAgregado) {
|
||||||
return $aAgregado ? 1 : -1;
|
return $aAgregado ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
$aImport = cc_test_import_time($a);
|
$aImport = cc_test_import_time($a);
|
||||||
@ -629,6 +629,7 @@ require_once 'layout_header.php';
|
|||||||
</div>
|
</div>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<a href="download_agregados_pedidos_template.php" class="btn btn-outline-primary btn-sm">Descargar plantilla Excel</a>
|
<a href="download_agregados_pedidos_template.php" class="btn btn-outline-primary btn-sm">Descargar plantilla Excel</a>
|
||||||
|
<div class="small text-muted mt-2">La plantilla sale con el mismo orden de columnas que tu Drive.</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -845,6 +846,7 @@ require_once 'layout_header.php';
|
|||||||
<div class="small"><strong>Departamento:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['sede'])); ?></div>
|
<div class="small"><strong>Departamento:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['sede'])); ?></div>
|
||||||
<div class="small"><strong>Provincia:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['ciudad'])); ?></div>
|
<div class="small"><strong>Provincia:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['ciudad'])); ?></div>
|
||||||
<div class="small"><strong>Distrito:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito'])); ?></div>
|
<div class="small"><strong>Distrito:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito'])); ?></div>
|
||||||
|
<div class="small"><strong>Coordenadas:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['coordenadas'], 'Sin coordenadas')); ?></div>
|
||||||
<?php if (!empty(trim((string) ($order['distrito_drive'] ?? '')))): ?>
|
<?php if (!empty(trim((string) ($order['distrito_drive'] ?? '')))): ?>
|
||||||
<div class="small"><strong>DISTRITO 1:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito_drive'])); ?></div>
|
<div class="small"><strong>DISTRITO 1:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito_drive'])); ?></div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@ -870,6 +872,9 @@ require_once 'layout_header.php';
|
|||||||
<?php if (!empty($order['fecha_entrega_programada'])): ?>
|
<?php if (!empty($order['fecha_entrega_programada'])): ?>
|
||||||
<div class="small text-muted">Entrega programada: <?php echo htmlspecialchars(cc_test_format_date($order['fecha_entrega_programada'] ?? null)); ?></div>
|
<div class="small text-muted">Entrega programada: <?php echo htmlspecialchars(cc_test_format_date($order['fecha_entrega_programada'] ?? null)); ?></div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<?php if (!empty($order['ruta_contraentrega_pedido_id'])): ?>
|
||||||
|
<div class="small text-success">Subido a Ruta Contraentrega #<?php echo (int) $order['ruta_contraentrega_pedido_id']; ?><?php if (!empty($order['ruta_contraentrega_subido_at'])): ?> · <?php echo htmlspecialchars(cc_test_format_datetime($order['ruta_contraentrega_subido_at'] ?? null, '')); ?><?php endif; ?></div>
|
||||||
|
<?php endif; ?>
|
||||||
<div class="small text-muted">Última gestión: <?php echo htmlspecialchars(cc_test_format_datetime($order['ultima_gestion_at'] ?? ($order['seguimiento_actualizado'] ?? null), 'Aún no gestionado')); ?></div>
|
<div class="small text-muted">Última gestión: <?php echo htmlspecialchars(cc_test_format_datetime($order['ultima_gestion_at'] ?? ($order['seguimiento_actualizado'] ?? null), 'Aún no gestionado')); ?></div>
|
||||||
<div class="small text-muted mt-1">Nota: <?php echo htmlspecialchars(cc_test_display_value($order['nota_seguimiento'], 'Sin nota interna')); ?></div>
|
<div class="small text-muted mt-1">Nota: <?php echo htmlspecialchars(cc_test_display_value($order['nota_seguimiento'], 'Sin nota interna')); ?></div>
|
||||||
</td>
|
</td>
|
||||||
@ -976,13 +981,27 @@ require_once 'layout_header.php';
|
|||||||
<div class="modal fade" id="<?php echo htmlspecialchars($modalId); ?>" tabindex="-1" aria-hidden="true">
|
<div class="modal fade" id="<?php echo htmlspecialchars($modalId); ?>" tabindex="-1" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header align-items-start gap-2">
|
||||||
<div>
|
<div class="flex-grow-1 min-w-0">
|
||||||
<div class="small text-primary fw-semibold mb-1"><?php echo htmlspecialchars(cc_test_order_label($order)); ?></div>
|
<div class="small text-primary fw-semibold mb-1"><?php echo htmlspecialchars(cc_test_order_label($order)); ?></div>
|
||||||
<h3 class="modal-title h5 mb-1"><?php echo htmlspecialchars(cc_test_display_value($order['nombre'], 'Cliente sin nombre')); ?></h3>
|
<div class="d-flex flex-wrap align-items-center justify-content-between gap-2">
|
||||||
<div class="small text-muted"><?php echo htmlspecialchars(cc_test_display_value($order['producto'], 'Sin producto')); ?> · <?php echo htmlspecialchars(cc_test_display_value($order['celular'], 'Sin celular')); ?></div>
|
<h3 class="modal-title h5 mb-0"><?php echo htmlspecialchars(cc_test_display_value($order['nombre'], 'Cliente sin nombre')); ?></h3>
|
||||||
|
<?php if ($storeKey === 'otra_tienda'): ?>
|
||||||
|
<button type="button" class="btn btn-primary btn-sm px-3" id="subir-ruta-<?php echo htmlspecialchars($order['source_key']); ?>" onclick="guardarGestion('<?php echo htmlspecialchars($order['source_key']); ?>', this, { subirRuta: true })"><?php echo !empty($order['ruta_contraentrega_pedido_id']) ? 'Actualizar en ruta' : 'Subir pedido'; ?></button>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<div class="small text-muted mt-1"><?php echo htmlspecialchars(cc_test_display_value($order['producto'], 'Sin producto')); ?> · <?php echo htmlspecialchars(cc_test_display_value($order['celular'], 'Sin celular')); ?></div>
|
||||||
|
<?php if ($storeKey === 'otra_tienda'): ?>
|
||||||
|
<div class="small mt-2 <?php echo !empty($order['ruta_contraentrega_pedido_id']) ? 'text-success fw-semibold' : 'text-muted'; ?>">
|
||||||
|
<?php if (!empty($order['ruta_contraentrega_pedido_id'])): ?>
|
||||||
|
En Ruta Contraentrega #<?php echo (int) $order['ruta_contraentrega_pedido_id']; ?>. Si cambias algo, usa este botón para actualizarlo.
|
||||||
|
<?php else: ?>
|
||||||
|
Súbelo cuando quede en <strong>CONFIRMADO CONTRAENTREGA</strong>.
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Cerrar"></button>
|
<button type="button" class="btn-close mt-1" data-bs-dismiss="modal" aria-label="Cerrar"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="border border-primary-subtle rounded-4 bg-primary-subtle p-2 mb-3" id="airDroidModalCard-<?php echo htmlspecialchars($order['source_key']); ?>">
|
<div class="border border-primary-subtle rounded-4 bg-primary-subtle p-2 mb-3" id="airDroidModalCard-<?php echo htmlspecialchars($order['source_key']); ?>">
|
||||||
@ -999,6 +1018,7 @@ require_once 'layout_header.php';
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="border border-success-subtle rounded-4 bg-white p-3 mb-4 shadow-sm cc-readonly-block" aria-disabled="true" style="user-select:none; -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none;">
|
<div class="border border-success-subtle rounded-4 bg-white p-3 mb-4 shadow-sm cc-readonly-block" aria-disabled="true" style="user-select:none; -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none;">
|
||||||
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-3">
|
<div class="d-flex flex-wrap justify-content-between align-items-center gap-2 mb-3">
|
||||||
<div>
|
<div>
|
||||||
@ -1139,8 +1159,8 @@ require_once 'layout_header.php';
|
|||||||
<div class="form-text">Úsalo cuando el cliente quede en Confirmado fecha.</div>
|
<div class="form-text">Úsalo cuando el cliente quede en Confirmado fecha.</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<label for="nota-<?php echo htmlspecialchars($order['source_key']); ?>" class="form-label">Nota interna</label>
|
<label for="nota-<?php echo htmlspecialchars($order['source_key']); ?>" class="form-label">COLOCAR AQUI OBSERVACION DEL CLIENTE O (DEDICATORIA O GRABADO)</label>
|
||||||
<textarea class="form-control" id="nota-<?php echo htmlspecialchars($order['source_key']); ?>" rows="3" placeholder="Ejemplo: cliente pidió volver a llamar después de las 5 pm."><?php echo htmlspecialchars($order['nota_seguimiento']); ?></textarea>
|
<textarea class="form-control" id="nota-<?php echo htmlspecialchars($order['source_key']); ?>" rows="3" placeholder="Ej.: Solicita dedicatoria para hija María, Ej.: Desea antes de las 4PM"><?php echo htmlspecialchars($order['nota_seguimiento']); ?></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -1209,6 +1229,11 @@ require_once 'layout_header.php';
|
|||||||
<input type="hidden" id="distrito-<?php echo htmlspecialchars($order['source_key']); ?>" value="<?php echo htmlspecialchars($distritoSeleccionado); ?>">
|
<input type="hidden" id="distrito-<?php echo htmlspecialchars($order['source_key']); ?>" value="<?php echo htmlspecialchars($distritoSeleccionado); ?>">
|
||||||
<div class="form-text">Si la provincia aún no tiene cobertura cargada, podrás escribir el distrito manualmente.</div>
|
<div class="form-text">Si la provincia aún no tiene cobertura cargada, podrás escribir el distrito manualmente.</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<label for="coordenadas-<?php echo htmlspecialchars($order['source_key']); ?>" class="form-label">Coordenadas</label>
|
||||||
|
<input type="text" class="form-control" id="coordenadas-<?php echo htmlspecialchars($order['source_key']); ?>" value="<?php echo htmlspecialchars((string) ($order['coordenadas'] ?? '')); ?>" inputmode="decimal" autocomplete="off" spellcheck="false" placeholder="-12.082029, -77.069024">
|
||||||
|
<div class="form-text">Obligatorias para <strong>Subir pedido</strong> a Ruta Contraentrega.</div>
|
||||||
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="agencia-<?php echo htmlspecialchars($order['source_key']); ?>" class="form-label">Agencia</label>
|
<label for="agencia-<?php echo htmlspecialchars($order['source_key']); ?>" class="form-label">Agencia</label>
|
||||||
<select class="form-select" id="agencia-<?php echo htmlspecialchars($order['source_key']); ?>">
|
<select class="form-select" id="agencia-<?php echo htmlspecialchars($order['source_key']); ?>">
|
||||||
@ -1247,7 +1272,8 @@ require_once 'layout_header.php';
|
|||||||
<div class="mb-1"><strong>Referencia Drive:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['referencia_drive'] ?? null)); ?></div>
|
<div class="mb-1"><strong>Referencia Drive:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['referencia_drive'] ?? null)); ?></div>
|
||||||
<div class="mb-1"><strong>Distrito 1:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito_drive'] ?? null)); ?></div>
|
<div class="mb-1"><strong>Distrito 1:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito_drive'] ?? null)); ?></div>
|
||||||
<div class="mb-1"><strong>Distrito:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito'] ?? null)); ?></div>
|
<div class="mb-1"><strong>Distrito:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['distrito'] ?? null)); ?></div>
|
||||||
<div><strong>Observación Drive:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['observaciones_drive'] ?? null)); ?></div>
|
<div class="mb-1"><strong>Observación Drive:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['observaciones_drive'] ?? null)); ?></div>
|
||||||
|
<div><strong>Coordenadas Drive:</strong> <?php echo htmlspecialchars(cc_test_display_value($order['coordenadas_drive'] ?? null)); ?></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4 class="h6 fw-bold mb-3">Historial de llamadas</h4>
|
<h4 class="h6 fw-bold mb-3">Historial de llamadas</h4>
|
||||||
@ -1272,9 +1298,16 @@ require_once 'layout_header.php';
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer d-flex justify-content-between">
|
|
||||||
<div class="small text-muted">Los cambios se guardan en la base local del módulo de prueba.</div>
|
<div class="modal-footer d-flex justify-content-between flex-wrap gap-2">
|
||||||
<div class="d-flex gap-2">
|
<div class="small text-muted">
|
||||||
|
<?php if ($storeKey === 'otra_tienda'): ?>
|
||||||
|
<strong>Guardar gestión</strong> solo guarda el historial. Para enviarlo a logística, usa <strong>Subir pedido</strong> junto al nombre del cliente.
|
||||||
|
<?php else: ?>
|
||||||
|
Los cambios se guardan en la base local del módulo de prueba.
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex gap-2 ms-auto">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
|
||||||
<button type="button" class="btn btn-primary" onclick="guardarGestion('<?php echo htmlspecialchars($order['source_key']); ?>', this)">Guardar gestión</button>
|
<button type="button" class="btn btn-primary" onclick="guardarGestion('<?php echo htmlspecialchars($order['source_key']); ?>', this)">Guardar gestión</button>
|
||||||
</div>
|
</div>
|
||||||
@ -1452,6 +1485,7 @@ function toggleAgendaFields(sourceKey) {
|
|||||||
const deliveryGroup = document.getElementById('delivery-group-' + sourceKey);
|
const deliveryGroup = document.getElementById('delivery-group-' + sourceKey);
|
||||||
const nextCallInput = document.getElementById('proxima-' + sourceKey);
|
const nextCallInput = document.getElementById('proxima-' + sourceKey);
|
||||||
const deliveryInput = document.getElementById('fecha-entrega-' + sourceKey);
|
const deliveryInput = document.getElementById('fecha-entrega-' + sourceKey);
|
||||||
|
const routeButton = document.getElementById('subir-ruta-' + sourceKey);
|
||||||
const needsDeliveryDate = estado === 'CONFIRMADO CONTRAENTREGA';
|
const needsDeliveryDate = estado === 'CONFIRMADO CONTRAENTREGA';
|
||||||
const needsNextCall = ['POR LLAMAR', 'DEVOLVER LLAMADA', 'OBSERVADO'].includes(estado);
|
const needsNextCall = ['POR LLAMAR', 'DEVOLVER LLAMADA', 'OBSERVADO'].includes(estado);
|
||||||
|
|
||||||
@ -1467,6 +1501,9 @@ function toggleAgendaFields(sourceKey) {
|
|||||||
if (!needsDeliveryDate && deliveryInput) {
|
if (!needsDeliveryDate && deliveryInput) {
|
||||||
deliveryInput.value = '';
|
deliveryInput.value = '';
|
||||||
}
|
}
|
||||||
|
if (routeButton) {
|
||||||
|
routeButton.disabled = !needsDeliveryDate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
@ -1558,7 +1595,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function guardarGestion(sourceKey, trigger) {
|
function guardarGestion(sourceKey, trigger, options = {}) {
|
||||||
|
const subirRuta = options.subirRuta === true;
|
||||||
const body = new URLSearchParams({
|
const body = new URLSearchParams({
|
||||||
source_key: sourceKey,
|
source_key: sourceKey,
|
||||||
estado: document.getElementById('estado-' + sourceKey)?.value || 'POR LLAMAR',
|
estado: document.getElementById('estado-' + sourceKey)?.value || 'POR LLAMAR',
|
||||||
@ -1572,6 +1610,7 @@ function guardarGestion(sourceKey, trigger) {
|
|||||||
sede: document.getElementById('sede-' + sourceKey)?.value || '',
|
sede: document.getElementById('sede-' + sourceKey)?.value || '',
|
||||||
ciudad: document.getElementById('ciudad-' + sourceKey)?.value || '',
|
ciudad: document.getElementById('ciudad-' + sourceKey)?.value || '',
|
||||||
distrito: document.getElementById('distrito-' + sourceKey)?.value || '',
|
distrito: document.getElementById('distrito-' + sourceKey)?.value || '',
|
||||||
|
coordenadas: document.getElementById('coordenadas-' + sourceKey)?.value || '',
|
||||||
dni: document.getElementById('dni-' + sourceKey)?.value || '',
|
dni: document.getElementById('dni-' + sourceKey)?.value || '',
|
||||||
observaciones: document.getElementById('observaciones-' + sourceKey)?.value || '',
|
observaciones: document.getElementById('observaciones-' + sourceKey)?.value || '',
|
||||||
producto: document.getElementById('producto-' + sourceKey)?.value || '',
|
producto: document.getElementById('producto-' + sourceKey)?.value || '',
|
||||||
@ -1582,7 +1621,8 @@ function guardarGestion(sourceKey, trigger) {
|
|||||||
confirmacion_precio: document.getElementById('confirmacion_precio-' + sourceKey)?.value || '',
|
confirmacion_precio: document.getElementById('confirmacion_precio-' + sourceKey)?.value || '',
|
||||||
confirmacion_producto_extra: document.getElementById('confirmacion_producto_extra-' + sourceKey)?.value || '',
|
confirmacion_producto_extra: document.getElementById('confirmacion_producto_extra-' + sourceKey)?.value || '',
|
||||||
confirmacion_cantidad_extra: document.getElementById('confirmacion_cantidad_extra-' + sourceKey)?.value || '',
|
confirmacion_cantidad_extra: document.getElementById('confirmacion_cantidad_extra-' + sourceKey)?.value || '',
|
||||||
confirmacion_precio_extra: document.getElementById('confirmacion_precio_extra-' + sourceKey)?.value || ''
|
confirmacion_precio_extra: document.getElementById('confirmacion_precio_extra-' + sourceKey)?.value || '',
|
||||||
|
subir_a_ruta: subirRuta ? '1' : '0'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (trigger) {
|
if (trigger) {
|
||||||
@ -1599,6 +1639,9 @@ function guardarGestion(sourceKey, trigger) {
|
|||||||
if (!data.success) {
|
if (!data.success) {
|
||||||
throw new Error(data.message || 'No se pudo guardar la gestión');
|
throw new Error(data.message || 'No se pudo guardar la gestión');
|
||||||
}
|
}
|
||||||
|
if (subirRuta) {
|
||||||
|
alert(data.message || 'Pedido subido a Ruta Contraentrega correctamente.');
|
||||||
|
}
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
|||||||
@ -39,6 +39,7 @@ function cc_test_ensure_tracking_table(PDO $pdo): void
|
|||||||
`distrito` VARCHAR(120) NULL,
|
`distrito` VARCHAR(120) NULL,
|
||||||
`dni` VARCHAR(40) NULL,
|
`dni` VARCHAR(40) NULL,
|
||||||
`observaciones` TEXT NULL,
|
`observaciones` TEXT NULL,
|
||||||
|
`coordenadas` VARCHAR(255) NULL,
|
||||||
`producto` VARCHAR(255) NULL,
|
`producto` VARCHAR(255) NULL,
|
||||||
`cantidad` VARCHAR(50) NULL,
|
`cantidad` VARCHAR(50) NULL,
|
||||||
`precio` VARCHAR(80) NULL,
|
`precio` VARCHAR(80) NULL,
|
||||||
@ -51,6 +52,9 @@ function cc_test_ensure_tracking_table(PDO $pdo): void
|
|||||||
`proxima_llamada_at` DATETIME NULL,
|
`proxima_llamada_at` DATETIME NULL,
|
||||||
`fecha_entrega_programada` DATE NULL,
|
`fecha_entrega_programada` DATE NULL,
|
||||||
`numero_cuenta_enviado_at` DATETIME NULL,
|
`numero_cuenta_enviado_at` DATETIME NULL,
|
||||||
|
`ruta_contraentrega_pedido_id` INT NULL,
|
||||||
|
`ruta_contraentrega_subido_at` DATETIME NULL,
|
||||||
|
`ruta_contraentrega_subido_por` INT NULL,
|
||||||
`ultima_gestion_at` DATETIME NULL,
|
`ultima_gestion_at` DATETIME NULL,
|
||||||
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
@ -69,7 +73,8 @@ function cc_test_ensure_tracking_table(PDO $pdo): void
|
|||||||
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'distrito', 'VARCHAR(120) NULL AFTER `ciudad`');
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'distrito', 'VARCHAR(120) NULL AFTER `ciudad`');
|
||||||
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'dni', 'VARCHAR(40) NULL AFTER `distrito`');
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'dni', 'VARCHAR(40) NULL AFTER `distrito`');
|
||||||
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'observaciones', 'TEXT NULL AFTER `dni`');
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'observaciones', 'TEXT NULL AFTER `dni`');
|
||||||
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'producto', 'VARCHAR(255) NULL AFTER `observaciones`');
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'coordenadas', 'VARCHAR(255) NULL AFTER `observaciones`');
|
||||||
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'producto', 'VARCHAR(255) NULL AFTER `coordenadas`');
|
||||||
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'cantidad', 'VARCHAR(50) NULL AFTER `producto`');
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'cantidad', 'VARCHAR(50) NULL AFTER `producto`');
|
||||||
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'precio', 'VARCHAR(80) NULL AFTER `cantidad`');
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'precio', 'VARCHAR(80) NULL AFTER `cantidad`');
|
||||||
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'confirmacion_producto', 'VARCHAR(255) NULL AFTER `precio`');
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'confirmacion_producto', 'VARCHAR(255) NULL AFTER `precio`');
|
||||||
@ -81,7 +86,10 @@ function cc_test_ensure_tracking_table(PDO $pdo): void
|
|||||||
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'proxima_llamada_at', 'DATETIME NULL AFTER `confirmacion_precio`');
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'proxima_llamada_at', 'DATETIME NULL AFTER `confirmacion_precio`');
|
||||||
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'fecha_entrega_programada', 'DATE NULL AFTER `proxima_llamada_at`');
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'fecha_entrega_programada', 'DATE NULL AFTER `proxima_llamada_at`');
|
||||||
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'numero_cuenta_enviado_at', 'DATETIME NULL AFTER `fecha_entrega_programada`');
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'numero_cuenta_enviado_at', 'DATETIME NULL AFTER `fecha_entrega_programada`');
|
||||||
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'ultima_gestion_at', 'DATETIME NULL AFTER `numero_cuenta_enviado_at`');
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'ruta_contraentrega_pedido_id', 'INT NULL AFTER `numero_cuenta_enviado_at`');
|
||||||
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'ruta_contraentrega_subido_at', 'DATETIME NULL AFTER `ruta_contraentrega_pedido_id`');
|
||||||
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'ruta_contraentrega_subido_por', 'INT NULL AFTER `ruta_contraentrega_subido_at`');
|
||||||
|
cc_test_ensure_column($pdo, 'callcenter_test_tracking', 'ultima_gestion_at', 'DATETIME NULL AFTER `ruta_contraentrega_subido_por`');
|
||||||
|
|
||||||
$checked = true;
|
$checked = true;
|
||||||
}
|
}
|
||||||
@ -311,6 +319,69 @@ function cc_test_state_label(string $estado): string
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cc_test_normalize_contraentrega_coordinates(string $value): ?string
|
||||||
|
{
|
||||||
|
$value = trim($value);
|
||||||
|
if ($value === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
function cc_test_parse_quantity(?string $value): ?int
|
||||||
|
{
|
||||||
|
$value = trim((string) $value);
|
||||||
|
if ($value === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!preg_match('/-?\d+/', $value, $matches)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cantidad = (int) $matches[0];
|
||||||
|
if ($cantidad <= 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $cantidad;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cc_test_parse_amount(?string $value): ?float
|
||||||
|
{
|
||||||
|
$value = trim((string) $value);
|
||||||
|
if ($value === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = str_ireplace(['S/', 'USD', '$'], '', $value);
|
||||||
|
$value = preg_replace('/\s+/', '', $value) ?? $value;
|
||||||
|
|
||||||
|
if (strpos($value, ',') !== false && strpos($value, '.') === false) {
|
||||||
|
$value = str_replace(',', '.', $value);
|
||||||
|
} else {
|
||||||
|
$value = str_replace(',', '', $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = preg_replace('/[^0-9.\-]/', '', $value) ?? $value;
|
||||||
|
if ($value === '' || !is_numeric($value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return round((float) $value, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function cc_test_row_background_style(string $estado): string
|
function cc_test_row_background_style(string $estado): string
|
||||||
|
|||||||
@ -223,7 +223,7 @@ function drive_test_fetch_tracking(PDO $pdo, array $sourceKeys): array
|
|||||||
cc_test_ensure_tracking_table($pdo);
|
cc_test_ensure_tracking_table($pdo);
|
||||||
|
|
||||||
$placeholders = implode(',', array_fill(0, count($sourceKeys), '?'));
|
$placeholders = implode(',', array_fill(0, count($sourceKeys), '?'));
|
||||||
$stmt = $pdo->prepare("SELECT source_key, estado, nota_seguimiento, user_id, direccion, referencia, agencia, sede_agencia, sede, ciudad, distrito, dni, observaciones, producto, cantidad, precio, confirmacion_producto, confirmacion_cantidad, confirmacion_precio, confirmacion_producto_extra, confirmacion_cantidad_extra, confirmacion_precio_extra, proxima_llamada_at, fecha_entrega_programada, numero_cuenta_enviado_at, ultima_gestion_at, updated_at FROM callcenter_test_tracking WHERE source_key IN ($placeholders)");
|
$stmt = $pdo->prepare("SELECT source_key, estado, nota_seguimiento, user_id, direccion, referencia, agencia, sede_agencia, sede, ciudad, distrito, dni, observaciones, coordenadas, producto, cantidad, precio, confirmacion_producto, confirmacion_cantidad, confirmacion_precio, confirmacion_producto_extra, confirmacion_cantidad_extra, confirmacion_precio_extra, proxima_llamada_at, fecha_entrega_programada, numero_cuenta_enviado_at, ruta_contraentrega_pedido_id, ruta_contraentrega_subido_at, ruta_contraentrega_subido_por, ultima_gestion_at, updated_at FROM callcenter_test_tracking WHERE source_key IN ($placeholders)");
|
||||||
$stmt->execute($sourceKeys);
|
$stmt->execute($sourceKeys);
|
||||||
|
|
||||||
$tracking = [];
|
$tracking = [];
|
||||||
@ -236,7 +236,7 @@ function drive_test_fetch_tracking(PDO $pdo, array $sourceKeys): array
|
|||||||
|
|
||||||
function drive_test_merge_tracking(array $orders, array $tracking): array
|
function drive_test_merge_tracking(array $orders, array $tracking): array
|
||||||
{
|
{
|
||||||
$editableFields = ['direccion', 'referencia', 'agencia', 'sede_agencia', 'sede', 'ciudad', 'distrito', 'dni', 'observaciones', 'producto', 'cantidad', 'precio', 'confirmacion_producto', 'confirmacion_cantidad', 'confirmacion_precio', 'confirmacion_producto_extra', 'confirmacion_cantidad_extra', 'confirmacion_precio_extra'];
|
$editableFields = ['direccion', 'referencia', 'agencia', 'sede_agencia', 'sede', 'ciudad', 'distrito', 'dni', 'observaciones', 'coordenadas', 'producto', 'cantidad', 'precio', 'confirmacion_producto', 'confirmacion_cantidad', 'confirmacion_precio', 'confirmacion_producto_extra', 'confirmacion_cantidad_extra', 'confirmacion_precio_extra'];
|
||||||
|
|
||||||
foreach ($orders as &$order) {
|
foreach ($orders as &$order) {
|
||||||
$current = $tracking[$order['source_key']] ?? null;
|
$current = $tracking[$order['source_key']] ?? null;
|
||||||
@ -248,6 +248,9 @@ function drive_test_merge_tracking(array $orders, array $tracking): array
|
|||||||
$order['proxima_llamada_at'] = $current['proxima_llamada_at'] ?? null;
|
$order['proxima_llamada_at'] = $current['proxima_llamada_at'] ?? null;
|
||||||
$order['fecha_entrega_programada'] = $current['fecha_entrega_programada'] ?? null;
|
$order['fecha_entrega_programada'] = $current['fecha_entrega_programada'] ?? null;
|
||||||
$order['numero_cuenta_enviado_at'] = $current['numero_cuenta_enviado_at'] ?? null;
|
$order['numero_cuenta_enviado_at'] = $current['numero_cuenta_enviado_at'] ?? null;
|
||||||
|
$order['ruta_contraentrega_pedido_id'] = isset($current['ruta_contraentrega_pedido_id']) && (int) $current['ruta_contraentrega_pedido_id'] > 0 ? (int) $current['ruta_contraentrega_pedido_id'] : null;
|
||||||
|
$order['ruta_contraentrega_subido_at'] = $current['ruta_contraentrega_subido_at'] ?? null;
|
||||||
|
$order['ruta_contraentrega_subido_por'] = isset($current['ruta_contraentrega_subido_por']) && (int) $current['ruta_contraentrega_subido_por'] > 0 ? (int) $current['ruta_contraentrega_subido_por'] : null;
|
||||||
$order['ultima_gestion_at'] = $current['ultima_gestion_at'] ?? ($current['updated_at'] ?? null);
|
$order['ultima_gestion_at'] = $current['ultima_gestion_at'] ?? ($current['updated_at'] ?? null);
|
||||||
|
|
||||||
foreach ($editableFields as $field) {
|
foreach ($editableFields as $field) {
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
session_start();
|
session_start();
|
||||||
require_once 'db/config.php';
|
require_once 'db/config.php';
|
||||||
require_once 'includes/callcenter_test_helpers.php';
|
require_once 'includes/callcenter_test_helpers.php';
|
||||||
|
require_once 'includes/contraentrega_cobertura.php';
|
||||||
|
|
||||||
header('Content-Type: application/json; charset=utf-8');
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
|
||||||
@ -31,9 +32,385 @@ function cc_test_normalize_nullable_text(string $key, int $maxLen = 3000): ?stri
|
|||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function cc_test_fetch_source_order(PDO $pdo, string $sourceKey): ?array
|
||||||
|
{
|
||||||
|
$stmt = $pdo->prepare(
|
||||||
|
'SELECT
|
||||||
|
source_key,
|
||||||
|
store_key,
|
||||||
|
codigo,
|
||||||
|
import_id,
|
||||||
|
nombre,
|
||||||
|
celular,
|
||||||
|
producto,
|
||||||
|
cantidad,
|
||||||
|
precio,
|
||||||
|
coordenadas,
|
||||||
|
direccion_drive,
|
||||||
|
referencia_drive,
|
||||||
|
sede_drive,
|
||||||
|
ciudad_drive,
|
||||||
|
distrito_drive,
|
||||||
|
dni_drive,
|
||||||
|
observaciones_drive
|
||||||
|
FROM callcenter_test_orders
|
||||||
|
WHERE source_key = ?
|
||||||
|
LIMIT 1'
|
||||||
|
);
|
||||||
|
$stmt->execute([$sourceKey]);
|
||||||
|
|
||||||
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
return $row ?: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cc_test_build_contraentrega_notes(array $parts): string
|
||||||
|
{
|
||||||
|
$cleanParts = [];
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
$part = trim((string) $part);
|
||||||
|
if ($part !== '') {
|
||||||
|
$cleanParts[] = $part;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode("\n\n", $cleanParts);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cc_test_prepare_route_order_payload(array $sourceOrder, array $formData, int $fallbackUserId): array
|
||||||
|
{
|
||||||
|
if (($sourceOrder['store_key'] ?? '') !== 'otra_tienda') {
|
||||||
|
throw new RuntimeException('En este primer paso la subida automática a ruta está activa solo para TUANI.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$nombreCompleto = trim((string) ($sourceOrder['nombre'] ?? ''));
|
||||||
|
$celular = trim((string) ($sourceOrder['celular'] ?? ''));
|
||||||
|
$direccion = trim((string) ($formData['direccion'] ?? ''));
|
||||||
|
$referencia = trim((string) ($formData['referencia'] ?? ''));
|
||||||
|
$departamento = trim((string) ($formData['sede'] ?? ''));
|
||||||
|
$provincia = trim((string) ($formData['ciudad'] ?? ''));
|
||||||
|
$distrito = trim((string) ($formData['distrito'] ?? ''));
|
||||||
|
$dni = trim((string) (($formData['dni'] ?? '') !== '' ? ($formData['dni'] ?? '') : ($sourceOrder['dni_drive'] ?? '')));
|
||||||
|
$observacionesPedido = trim((string) (($formData['observaciones'] ?? '') !== '' ? ($formData['observaciones'] ?? '') : ($sourceOrder['observaciones_drive'] ?? '')));
|
||||||
|
$notaSeguimiento = trim((string) ($formData['nota_seguimiento'] ?? ''));
|
||||||
|
$fechaEntrega = $formData['fecha_entrega_programada'] ?? null;
|
||||||
|
$coordenadasRaw = trim((string) ($formData['coordenadas'] ?? ''));
|
||||||
|
|
||||||
|
if ($nombreCompleto === '' || $celular === '') {
|
||||||
|
throw new RuntimeException('El pedido no tiene nombre o celular suficientes para enviarlo a Ruta Contraentrega.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($fechaEntrega === null || $fechaEntrega === '') {
|
||||||
|
throw new RuntimeException('Debes seleccionar la fecha de entrega antes de subir el pedido.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($direccion === '' || $departamento === '' || $provincia === '' || $distrito === '') {
|
||||||
|
throw new RuntimeException('Para subir el pedido completa dirección, departamento, provincia y distrito.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$departamentos = contraentregaProvinciasPorDepartamento();
|
||||||
|
$distritosPorProvincia = contraentregaDistritosPorProvincia();
|
||||||
|
|
||||||
|
if (!array_key_exists($departamento, $departamentos)) {
|
||||||
|
throw new RuntimeException('Selecciona un departamento válido para Ruta Contraentrega.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$provinciasPermitidas = $departamentos[$departamento] ?? [];
|
||||||
|
if ($provincia === '' || !in_array($provincia, $provinciasPermitidas, true)) {
|
||||||
|
throw new RuntimeException('Selecciona una provincia válida para el departamento elegido.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$distritosPermitidos = $distritosPorProvincia[$provincia] ?? null;
|
||||||
|
if (is_array($distritosPermitidos) && !empty($distritosPermitidos) && !in_array($distrito, $distritosPermitidos, true)) {
|
||||||
|
throw new RuntimeException('Selecciona un distrito válido para la provincia elegida.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$coordenadas = cc_test_normalize_contraentrega_coordinates($coordenadasRaw);
|
||||||
|
if ($coordenadas === null) {
|
||||||
|
throw new RuntimeException('Ingresa coordenadas válidas con el formato -12.082029, -77.069024.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$productoBase = trim((string) ($formData['producto'] ?? ''));
|
||||||
|
if ($productoBase === '') {
|
||||||
|
$productoBase = trim((string) ($sourceOrder['producto'] ?? ''));
|
||||||
|
}
|
||||||
|
$cantidadBase = trim((string) ($formData['cantidad'] ?? ''));
|
||||||
|
if ($cantidadBase === '') {
|
||||||
|
$cantidadBase = trim((string) ($sourceOrder['cantidad'] ?? ''));
|
||||||
|
}
|
||||||
|
$precioBase = trim((string) ($formData['precio'] ?? ''));
|
||||||
|
if ($precioBase === '') {
|
||||||
|
$precioBase = trim((string) ($sourceOrder['precio'] ?? ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
$productoPrincipal = trim((string) ($formData['confirmacion_producto'] ?? ''));
|
||||||
|
if ($productoPrincipal === '') {
|
||||||
|
$productoPrincipal = $productoBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cantidadPrincipalRaw = trim((string) ($formData['confirmacion_cantidad'] ?? ''));
|
||||||
|
if ($cantidadPrincipalRaw === '') {
|
||||||
|
$cantidadPrincipalRaw = $cantidadBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
$precioPrincipalRaw = trim((string) ($formData['confirmacion_precio'] ?? ''));
|
||||||
|
if ($precioPrincipalRaw === '') {
|
||||||
|
$precioPrincipalRaw = $precioBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($productoPrincipal === '') {
|
||||||
|
throw new RuntimeException('El pedido no tiene producto principal para subir a Ruta Contraentrega.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$cantidadPrincipal = cc_test_parse_quantity($cantidadPrincipalRaw);
|
||||||
|
if ($cantidadPrincipal === null) {
|
||||||
|
throw new RuntimeException('La cantidad principal del pedido no es válida.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$precioPrincipal = cc_test_parse_amount($precioPrincipalRaw);
|
||||||
|
if ($precioPrincipal === null) {
|
||||||
|
throw new RuntimeException('El precio principal del pedido no es válido.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$productoExtra = trim((string) ($formData['confirmacion_producto_extra'] ?? ''));
|
||||||
|
$cantidadExtraRaw = trim((string) ($formData['confirmacion_cantidad_extra'] ?? ''));
|
||||||
|
$precioExtraRaw = trim((string) ($formData['confirmacion_precio_extra'] ?? ''));
|
||||||
|
$hayExtra = $productoExtra !== '' || $cantidadExtraRaw !== '' || $precioExtraRaw !== '';
|
||||||
|
|
||||||
|
$productos = [$productoPrincipal];
|
||||||
|
$detalleProductos = [$productoPrincipal . ' (x' . $cantidadPrincipal . ')'];
|
||||||
|
$cantidadTotal = $cantidadPrincipal;
|
||||||
|
$montoTotal = $precioPrincipal;
|
||||||
|
|
||||||
|
if ($hayExtra) {
|
||||||
|
if ($productoExtra === '' || $cantidadExtraRaw === '' || $precioExtraRaw === '') {
|
||||||
|
throw new RuntimeException('Si usas producto adicional, completa producto, cantidad y precio adicional.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$cantidadExtra = cc_test_parse_quantity($cantidadExtraRaw);
|
||||||
|
if ($cantidadExtra === null) {
|
||||||
|
throw new RuntimeException('La cantidad del producto adicional no es válida.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$precioExtra = cc_test_parse_amount($precioExtraRaw);
|
||||||
|
if ($precioExtra === null) {
|
||||||
|
throw new RuntimeException('El precio del producto adicional no es válido.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$productos[] = $productoExtra;
|
||||||
|
$detalleProductos[] = $productoExtra . ' (x' . $cantidadExtra . ')';
|
||||||
|
$cantidadTotal += $cantidadExtra;
|
||||||
|
$montoTotal += $precioExtra;
|
||||||
|
}
|
||||||
|
|
||||||
|
$identificadorPedido = trim((string) ($sourceOrder['codigo'] ?? ''));
|
||||||
|
if ($identificadorPedido === '') {
|
||||||
|
$identificadorPedido = trim((string) ($sourceOrder['import_id'] ?? ''));
|
||||||
|
}
|
||||||
|
if ($identificadorPedido === '') {
|
||||||
|
$identificadorPedido = 'source:' . substr((string) ($sourceOrder['source_key'] ?? ''), 0, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
$notas = cc_test_build_contraentrega_notes([
|
||||||
|
'Origen: Call Center TUANI',
|
||||||
|
'Pedido base: ' . $identificadorPedido,
|
||||||
|
'Detalle confirmado: ' . implode(', ', $detalleProductos),
|
||||||
|
$observacionesPedido !== '' ? 'Observaciones del pedido: ' . $observacionesPedido : '',
|
||||||
|
$notaSeguimiento !== '' ? 'Nota interna Call Center: ' . $notaSeguimiento : '',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$seguimiento = 'Subido desde Call Center TUANI';
|
||||||
|
$codigoTracking = trim((string) ($sourceOrder['codigo'] ?? ''));
|
||||||
|
|
||||||
|
return [
|
||||||
|
'source_key' => (string) ($sourceOrder['source_key'] ?? ''),
|
||||||
|
'dni_cliente' => $dni,
|
||||||
|
'nombre_completo' => $nombreCompleto,
|
||||||
|
'celular' => $celular,
|
||||||
|
'agencia' => 'CONTRAENTREGA',
|
||||||
|
'sede_envio' => $departamento,
|
||||||
|
'codigo_rastreo' => trim($provincia . ' / ' . $distrito, ' /'),
|
||||||
|
'codigo_tracking' => $codigoTracking !== '' ? $codigoTracking : null,
|
||||||
|
'direccion_exacta' => $direccion,
|
||||||
|
'referencia_domicilio' => $referencia !== '' ? $referencia : null,
|
||||||
|
'coordenadas' => $coordenadas,
|
||||||
|
'producto' => implode(', ', $productos),
|
||||||
|
'cantidad' => $cantidadTotal,
|
||||||
|
'monto_total' => round($montoTotal, 2),
|
||||||
|
'asesor_id' => $fallbackUserId > 0 ? $fallbackUserId : null,
|
||||||
|
'notas' => $notas,
|
||||||
|
'nota_adicional' => $notaSeguimiento !== '' ? $notaSeguimiento : null,
|
||||||
|
'observacion' => $observacionesPedido !== '' ? $observacionesPedido : null,
|
||||||
|
'descargo' => $observacionesPedido !== '' ? $observacionesPedido : null,
|
||||||
|
'seguimiento' => $seguimiento,
|
||||||
|
'fecha_entrega' => $fechaEntrega,
|
||||||
|
'tipo_paquete' => 'CONTRAENTREGA',
|
||||||
|
'estado' => 'RUTA_CONTRAENTREGA',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function cc_test_sync_route_order(PDO $pdo, ?int $existingPedidoId, array $payload): array
|
||||||
|
{
|
||||||
|
$existing = null;
|
||||||
|
if ($existingPedidoId !== null && $existingPedidoId > 0) {
|
||||||
|
$stmtExisting = $pdo->prepare('SELECT * FROM pedidos WHERE id = ? LIMIT 1');
|
||||||
|
$stmtExisting->execute([$existingPedidoId]);
|
||||||
|
$existing = $stmtExisting->fetch(PDO::FETCH_ASSOC) ?: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($existing) {
|
||||||
|
$montoAdelantado = round((float) ($existing['monto_adelantado'] ?? 0), 2);
|
||||||
|
$montoDebe = round(max(0, $payload['monto_total'] - $montoAdelantado), 2);
|
||||||
|
|
||||||
|
$stmtUpdate = $pdo->prepare(
|
||||||
|
'UPDATE pedidos SET
|
||||||
|
dni_cliente = :dni_cliente,
|
||||||
|
nombre_completo = :nombre_completo,
|
||||||
|
celular = :celular,
|
||||||
|
agencia = :agencia,
|
||||||
|
sede_envio = :sede_envio,
|
||||||
|
codigo_rastreo = :codigo_rastreo,
|
||||||
|
codigo_tracking = COALESCE(NULLIF(:codigo_tracking, \'\'), codigo_tracking),
|
||||||
|
referencia_domicilio = :referencia_domicilio,
|
||||||
|
direccion_exacta = :direccion_exacta,
|
||||||
|
coordenadas = :coordenadas,
|
||||||
|
producto = :producto,
|
||||||
|
cantidad = :cantidad,
|
||||||
|
monto_total = :monto_total,
|
||||||
|
monto_debe = :monto_debe,
|
||||||
|
asesor_id = :asesor_id,
|
||||||
|
notas = :notas,
|
||||||
|
nota_adicional = :nota_adicional,
|
||||||
|
observacion = :observacion,
|
||||||
|
descargo = :descargo,
|
||||||
|
seguimiento = :seguimiento,
|
||||||
|
fecha_entrega = :fecha_entrega,
|
||||||
|
tipo_paquete = :tipo_paquete,
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE id = :id'
|
||||||
|
);
|
||||||
|
|
||||||
|
$stmtUpdate->execute([
|
||||||
|
':dni_cliente' => $payload['dni_cliente'],
|
||||||
|
':nombre_completo' => $payload['nombre_completo'],
|
||||||
|
':celular' => $payload['celular'],
|
||||||
|
':agencia' => $payload['agencia'],
|
||||||
|
':sede_envio' => $payload['sede_envio'],
|
||||||
|
':codigo_rastreo' => $payload['codigo_rastreo'],
|
||||||
|
':codigo_tracking' => $payload['codigo_tracking'] ?? '',
|
||||||
|
':referencia_domicilio' => $payload['referencia_domicilio'],
|
||||||
|
':direccion_exacta' => $payload['direccion_exacta'],
|
||||||
|
':coordenadas' => $payload['coordenadas'],
|
||||||
|
':producto' => $payload['producto'],
|
||||||
|
':cantidad' => $payload['cantidad'],
|
||||||
|
':monto_total' => $payload['monto_total'],
|
||||||
|
':monto_debe' => $montoDebe,
|
||||||
|
':asesor_id' => $payload['asesor_id'],
|
||||||
|
':notas' => !empty(trim((string) ($existing['notas'] ?? ''))) ? $existing['notas'] : $payload['notas'],
|
||||||
|
':nota_adicional' => !empty(trim((string) ($existing['nota_adicional'] ?? ''))) ? $existing['nota_adicional'] : $payload['nota_adicional'],
|
||||||
|
':observacion' => !empty(trim((string) ($existing['observacion'] ?? ''))) ? $existing['observacion'] : $payload['observacion'],
|
||||||
|
':descargo' => !empty(trim((string) ($existing['descargo'] ?? ''))) ? $existing['descargo'] : $payload['descargo'],
|
||||||
|
':seguimiento' => !empty(trim((string) ($existing['seguimiento'] ?? ''))) ? $existing['seguimiento'] : $payload['seguimiento'],
|
||||||
|
':fecha_entrega' => $payload['fecha_entrega'],
|
||||||
|
':tipo_paquete' => $payload['tipo_paquete'],
|
||||||
|
':id' => (int) $existing['id'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'pedido_id' => (int) $existing['id'],
|
||||||
|
'action' => 'updated',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmtInsert = $pdo->prepare(
|
||||||
|
'INSERT INTO pedidos (
|
||||||
|
dni_cliente,
|
||||||
|
nombre_completo,
|
||||||
|
celular,
|
||||||
|
agencia,
|
||||||
|
sede_envio,
|
||||||
|
codigo_rastreo,
|
||||||
|
codigo_tracking,
|
||||||
|
referencia_domicilio,
|
||||||
|
direccion_exacta,
|
||||||
|
coordenadas,
|
||||||
|
producto,
|
||||||
|
cantidad,
|
||||||
|
monto_total,
|
||||||
|
monto_adelantado,
|
||||||
|
monto_debe,
|
||||||
|
estado,
|
||||||
|
asesor_id,
|
||||||
|
notas,
|
||||||
|
nota_adicional,
|
||||||
|
observacion,
|
||||||
|
descargo,
|
||||||
|
seguimiento,
|
||||||
|
fecha_entrega,
|
||||||
|
tipo_paquete
|
||||||
|
) VALUES (
|
||||||
|
:dni_cliente,
|
||||||
|
:nombre_completo,
|
||||||
|
:celular,
|
||||||
|
:agencia,
|
||||||
|
:sede_envio,
|
||||||
|
:codigo_rastreo,
|
||||||
|
:codigo_tracking,
|
||||||
|
:referencia_domicilio,
|
||||||
|
:direccion_exacta,
|
||||||
|
:coordenadas,
|
||||||
|
:producto,
|
||||||
|
:cantidad,
|
||||||
|
:monto_total,
|
||||||
|
0,
|
||||||
|
:monto_debe,
|
||||||
|
:estado,
|
||||||
|
:asesor_id,
|
||||||
|
:notas,
|
||||||
|
:nota_adicional,
|
||||||
|
:observacion,
|
||||||
|
:descargo,
|
||||||
|
:seguimiento,
|
||||||
|
:fecha_entrega,
|
||||||
|
:tipo_paquete
|
||||||
|
)'
|
||||||
|
);
|
||||||
|
|
||||||
|
$stmtInsert->execute([
|
||||||
|
':dni_cliente' => $payload['dni_cliente'],
|
||||||
|
':nombre_completo' => $payload['nombre_completo'],
|
||||||
|
':celular' => $payload['celular'],
|
||||||
|
':agencia' => $payload['agencia'],
|
||||||
|
':sede_envio' => $payload['sede_envio'],
|
||||||
|
':codigo_rastreo' => $payload['codigo_rastreo'],
|
||||||
|
':codigo_tracking' => $payload['codigo_tracking'],
|
||||||
|
':referencia_domicilio' => $payload['referencia_domicilio'],
|
||||||
|
':direccion_exacta' => $payload['direccion_exacta'],
|
||||||
|
':coordenadas' => $payload['coordenadas'],
|
||||||
|
':producto' => $payload['producto'],
|
||||||
|
':cantidad' => $payload['cantidad'],
|
||||||
|
':monto_total' => $payload['monto_total'],
|
||||||
|
':monto_debe' => $payload['monto_total'],
|
||||||
|
':estado' => $payload['estado'],
|
||||||
|
':asesor_id' => $payload['asesor_id'],
|
||||||
|
':notas' => $payload['notas'],
|
||||||
|
':nota_adicional' => $payload['nota_adicional'],
|
||||||
|
':observacion' => $payload['observacion'],
|
||||||
|
':descargo' => $payload['descargo'],
|
||||||
|
':seguimiento' => $payload['seguimiento'],
|
||||||
|
':fecha_entrega' => $payload['fecha_entrega'],
|
||||||
|
':tipo_paquete' => $payload['tipo_paquete'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'pedido_id' => (int) $pdo->lastInsertId(),
|
||||||
|
'action' => 'created',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
$sourceKey = trim((string) ($_POST['source_key'] ?? ''));
|
$sourceKey = trim((string) ($_POST['source_key'] ?? ''));
|
||||||
$estado = cc_test_normalize_state(trim((string) ($_POST['estado'] ?? 'POR LLAMAR')));
|
$estado = cc_test_normalize_state(trim((string) ($_POST['estado'] ?? 'POR LLAMAR')));
|
||||||
$validStates = cc_test_valid_states();
|
$validStates = cc_test_valid_states();
|
||||||
|
$subirARuta = (string) ($_POST['subir_a_ruta'] ?? '') === '1';
|
||||||
|
|
||||||
if ($sourceKey === '' || !preg_match('/^[a-f0-9]{40}$/', $sourceKey)) {
|
if ($sourceKey === '' || !preg_match('/^[a-f0-9]{40}$/', $sourceKey)) {
|
||||||
http_response_code(400);
|
http_response_code(400);
|
||||||
@ -56,6 +433,7 @@ try {
|
|||||||
$sede = cc_test_normalize_nullable_text('sede', 120);
|
$sede = cc_test_normalize_nullable_text('sede', 120);
|
||||||
$ciudad = cc_test_normalize_nullable_text('ciudad', 120);
|
$ciudad = cc_test_normalize_nullable_text('ciudad', 120);
|
||||||
$distrito = cc_test_normalize_nullable_text('distrito', 120);
|
$distrito = cc_test_normalize_nullable_text('distrito', 120);
|
||||||
|
$coordenadas = cc_test_normalize_nullable_text('coordenadas', 255);
|
||||||
$dni = cc_test_normalize_nullable_text('dni', 40);
|
$dni = cc_test_normalize_nullable_text('dni', 40);
|
||||||
$observaciones = cc_test_normalize_nullable_text('observaciones', 3000);
|
$observaciones = cc_test_normalize_nullable_text('observaciones', 3000);
|
||||||
$producto = cc_test_normalize_nullable_text('producto', 255);
|
$producto = cc_test_normalize_nullable_text('producto', 255);
|
||||||
@ -71,7 +449,7 @@ try {
|
|||||||
$pdo = db();
|
$pdo = db();
|
||||||
cc_test_ensure_tracking_table($pdo);
|
cc_test_ensure_tracking_table($pdo);
|
||||||
|
|
||||||
$stmtCurrent = $pdo->prepare('SELECT estado, numero_cuenta_enviado_at, user_id FROM callcenter_test_tracking WHERE source_key = ? LIMIT 1');
|
$stmtCurrent = $pdo->prepare('SELECT estado, numero_cuenta_enviado_at, user_id, ruta_contraentrega_pedido_id FROM callcenter_test_tracking WHERE source_key = ? LIMIT 1');
|
||||||
$stmtCurrent->execute([$sourceKey]);
|
$stmtCurrent->execute([$sourceKey]);
|
||||||
$currentTracking = $stmtCurrent->fetch(PDO::FETCH_ASSOC) ?: null;
|
$currentTracking = $stmtCurrent->fetch(PDO::FETCH_ASSOC) ?: null;
|
||||||
|
|
||||||
@ -88,7 +466,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$userIdToSet = $isAdmin
|
$userIdToSet = $isAdmin
|
||||||
? ($currentTracking ? ($currentTracking['user_id'] ?? null) : null)
|
? ($currentTracking ? ((int) ($currentTracking['user_id'] ?? 0) > 0 ? (int) $currentTracking['user_id'] : null) : null)
|
||||||
: (int) $_SESSION['user_id'];
|
: (int) $_SESSION['user_id'];
|
||||||
|
|
||||||
$proximaRaw = trim((string) ($_POST['proxima_llamada_at'] ?? ''));
|
$proximaRaw = trim((string) ($_POST['proxima_llamada_at'] ?? ''));
|
||||||
@ -131,6 +509,36 @@ try {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($subirARuta && $estado !== 'CONFIRMADO CONTRAENTREGA') {
|
||||||
|
throw new RuntimeException('Para subir el pedido a ruta, el estado debe ser CONFIRMADO CONTRAENTREGA.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$formData = [
|
||||||
|
'nota_seguimiento' => $nota,
|
||||||
|
'direccion' => $direccion,
|
||||||
|
'referencia' => $referencia,
|
||||||
|
'agencia' => $agencia,
|
||||||
|
'sede_agencia' => $sedeAgencia,
|
||||||
|
'sede' => $sede,
|
||||||
|
'ciudad' => $ciudad,
|
||||||
|
'distrito' => $distrito,
|
||||||
|
'coordenadas' => $coordenadas,
|
||||||
|
'dni' => $dni,
|
||||||
|
'observaciones' => $observaciones,
|
||||||
|
'producto' => $producto,
|
||||||
|
'cantidad' => $cantidad,
|
||||||
|
'precio' => $precio,
|
||||||
|
'confirmacion_producto' => $confirmacionProducto,
|
||||||
|
'confirmacion_cantidad' => $confirmacionCantidad,
|
||||||
|
'confirmacion_precio' => $confirmacionPrecio,
|
||||||
|
'confirmacion_producto_extra' => $confirmacionProductoExtra,
|
||||||
|
'confirmacion_cantidad_extra' => $confirmacionCantidadExtra,
|
||||||
|
'confirmacion_precio_extra' => $confirmacionPrecioExtra,
|
||||||
|
'fecha_entrega_programada' => $fechaEntrega,
|
||||||
|
];
|
||||||
|
|
||||||
|
$pdo->beginTransaction();
|
||||||
|
|
||||||
$stmt = $pdo->prepare(
|
$stmt = $pdo->prepare(
|
||||||
'INSERT INTO callcenter_test_tracking (
|
'INSERT INTO callcenter_test_tracking (
|
||||||
source_key,
|
source_key,
|
||||||
@ -144,6 +552,7 @@ try {
|
|||||||
sede,
|
sede,
|
||||||
ciudad,
|
ciudad,
|
||||||
distrito,
|
distrito,
|
||||||
|
coordenadas,
|
||||||
dni,
|
dni,
|
||||||
observaciones,
|
observaciones,
|
||||||
producto,
|
producto,
|
||||||
@ -171,6 +580,7 @@ try {
|
|||||||
:sede,
|
:sede,
|
||||||
:ciudad,
|
:ciudad,
|
||||||
:distrito,
|
:distrito,
|
||||||
|
:coordenadas,
|
||||||
:dni,
|
:dni,
|
||||||
:observaciones,
|
:observaciones,
|
||||||
:producto,
|
:producto,
|
||||||
@ -198,6 +608,7 @@ try {
|
|||||||
sede = VALUES(sede),
|
sede = VALUES(sede),
|
||||||
ciudad = VALUES(ciudad),
|
ciudad = VALUES(ciudad),
|
||||||
distrito = VALUES(distrito),
|
distrito = VALUES(distrito),
|
||||||
|
coordenadas = VALUES(coordenadas),
|
||||||
dni = VALUES(dni),
|
dni = VALUES(dni),
|
||||||
observaciones = VALUES(observaciones),
|
observaciones = VALUES(observaciones),
|
||||||
producto = VALUES(producto),
|
producto = VALUES(producto),
|
||||||
@ -228,6 +639,7 @@ try {
|
|||||||
':sede' => $sede,
|
':sede' => $sede,
|
||||||
':ciudad' => $ciudad,
|
':ciudad' => $ciudad,
|
||||||
':distrito' => $distrito,
|
':distrito' => $distrito,
|
||||||
|
':coordenadas' => $coordenadas,
|
||||||
':dni' => $dni,
|
':dni' => $dni,
|
||||||
':observaciones' => $observaciones,
|
':observaciones' => $observaciones,
|
||||||
':producto' => $producto,
|
':producto' => $producto,
|
||||||
@ -244,15 +656,69 @@ try {
|
|||||||
':numero_cuenta_enviado_at' => $numeroCuentaEnviadoAt,
|
':numero_cuenta_enviado_at' => $numeroCuentaEnviadoAt,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$rutaPedidoId = isset($currentTracking['ruta_contraentrega_pedido_id']) && (int) $currentTracking['ruta_contraentrega_pedido_id'] > 0
|
||||||
|
? (int) $currentTracking['ruta_contraentrega_pedido_id']
|
||||||
|
: null;
|
||||||
|
$rutaSubidoAt = null;
|
||||||
|
$rutaAction = null;
|
||||||
|
|
||||||
|
if ($subirARuta) {
|
||||||
|
$sourceOrder = cc_test_fetch_source_order($pdo, $sourceKey);
|
||||||
|
if (!$sourceOrder) {
|
||||||
|
throw new RuntimeException('No encontré el pedido base para enviarlo a Ruta Contraentrega.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$routePayload = cc_test_prepare_route_order_payload(
|
||||||
|
$sourceOrder,
|
||||||
|
$formData,
|
||||||
|
(int) ($userIdToSet ?: ($_SESSION['user_id'] ?? 0))
|
||||||
|
);
|
||||||
|
|
||||||
|
$routeSync = cc_test_sync_route_order($pdo, $rutaPedidoId, $routePayload);
|
||||||
|
$rutaPedidoId = (int) $routeSync['pedido_id'];
|
||||||
|
$rutaAction = $routeSync['action'];
|
||||||
|
$rutaSubidoAt = (new DateTimeImmutable('now'))->format('Y-m-d H:i:s');
|
||||||
|
|
||||||
|
$stmtRuta = $pdo->prepare(
|
||||||
|
'UPDATE callcenter_test_tracking
|
||||||
|
SET ruta_contraentrega_pedido_id = :pedido_id,
|
||||||
|
ruta_contraentrega_subido_at = :subido_at,
|
||||||
|
ruta_contraentrega_subido_por = :subido_por,
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE source_key = :source_key'
|
||||||
|
);
|
||||||
|
$stmtRuta->execute([
|
||||||
|
':pedido_id' => $rutaPedidoId,
|
||||||
|
':subido_at' => $rutaSubidoAt,
|
||||||
|
':subido_por' => (int) ($_SESSION['user_id'] ?? 0),
|
||||||
|
':source_key' => $sourceKey,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo->commit();
|
||||||
|
|
||||||
|
$message = 'Gestión actualizada correctamente.';
|
||||||
|
if ($subirARuta && $rutaPedidoId !== null) {
|
||||||
|
$message = $rutaAction === 'updated'
|
||||||
|
? 'Pedido actualizado en Ruta Contraentrega #' . $rutaPedidoId . '.'
|
||||||
|
: 'Pedido subido a Ruta Contraentrega #' . $rutaPedidoId . '.';
|
||||||
|
}
|
||||||
|
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => 'Gestión actualizada correctamente.',
|
'message' => $message,
|
||||||
'estado' => $estado,
|
'estado' => $estado,
|
||||||
'proxima_llamada_at' => $proximaLlamada,
|
'proxima_llamada_at' => $proximaLlamada,
|
||||||
'fecha_entrega_programada' => $fechaEntrega,
|
'fecha_entrega_programada' => $fechaEntrega,
|
||||||
'numero_cuenta_enviado_at' => $numeroCuentaEnviadoAt,
|
'numero_cuenta_enviado_at' => $numeroCuentaEnviadoAt,
|
||||||
|
'ruta_contraentrega_pedido_id' => $rutaPedidoId,
|
||||||
|
'ruta_contraentrega_subido_at' => $rutaSubidoAt,
|
||||||
]);
|
]);
|
||||||
} catch (Throwable $exception) {
|
} catch (Throwable $exception) {
|
||||||
|
if (isset($pdo) && $pdo instanceof PDO && $pdo->inTransaction()) {
|
||||||
|
$pdo->rollBack();
|
||||||
|
}
|
||||||
|
|
||||||
http_response_code(500);
|
http_response_code(500);
|
||||||
error_log('update_callcenter_test_tracking.php: ' . $exception->getMessage());
|
error_log('update_callcenter_test_tracking.php: ' . $exception->getMessage());
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user