Autosave: 20260421-192611

This commit is contained in:
Flatlogic Bot 2026-04-21 19:26:12 +00:00
parent 5de02535d2
commit 7eb4c17bef
9 changed files with 437 additions and 7 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 KiB

View File

@ -136,13 +136,13 @@ include 'layout_header.php';
<thead> <thead>
<tr> <tr>
<th>ID</th> <th>ID</th>
<th>Clave</th>
<th>Cliente</th> <th>Cliente</th>
<th>Celular</th> <th>Celular</th>
<th>Producto</th> <th>Producto</th>
<th>Monto Total</th> <th>Monto Total</th>
<th>Monto Debe</th> <th>Monto Debe</th>
<th>Nro. Operación</th> <th>Nro. Operación</th>
<th>Clave</th>
<th>Banco</th> <th>Banco</th>
<th>Recojo Cliente (Día y Hora)</th> <th>Recojo Cliente (Día y Hora)</th>
<th>Estado</th> <th>Estado</th>
@ -163,6 +163,12 @@ include 'layout_header.php';
<?php foreach ($pedidos as $pedido): ?> <?php foreach ($pedidos as $pedido): ?>
<tr> <tr>
<td><?php echo htmlspecialchars($pedido['id']); ?></td> <td><?php echo htmlspecialchars($pedido['id']); ?></td>
<td><?php echo htmlspecialchars($pedido['nombre_completo']); ?></td>
<td><?php echo htmlspecialchars($pedido['celular']); ?></td>
<td><?php echo htmlspecialchars($pedido['producto']); ?></td>
<td><?php echo htmlspecialchars($pedido['monto_total']); ?></td>
<td><?php echo htmlspecialchars($pedido['monto_debe']); ?></td>
<td><?php echo htmlspecialchars($pedido['numero_operacion'] ?? 'N/A'); ?></td>
<?php <?php
$canSeeClave = ($user_role !== 'Asesor' || !empty($pedido['numero_operacion'])); $canSeeClave = ($user_role !== 'Asesor' || !empty($pedido['numero_operacion']));
$isEditableClave = ($user_role !== 'Asesor') ? 'editable' : ''; $isEditableClave = ($user_role !== 'Asesor') ? 'editable' : '';
@ -170,12 +176,6 @@ include 'layout_header.php';
<td class="<?php echo $isEditableClave; ?>" data-id="<?php echo $pedido['id']; ?>" data-field="clave"> <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 para ver la clave"></i> <span class="text-muted" style="font-size: 0.8rem;">Oculto</span>'; ?> <?php echo $canSeeClave ? htmlspecialchars($pedido['clave'] ?? 'N/A') : '<i class="fas fa-eye-slash text-muted" title="Suba el número de operación para ver la clave"></i> <span class="text-muted" style="font-size: 0.8rem;">Oculto</span>'; ?>
</td> </td>
<td><?php echo htmlspecialchars($pedido['nombre_completo']); ?></td>
<td><?php echo htmlspecialchars($pedido['celular']); ?></td>
<td><?php echo htmlspecialchars($pedido['producto']); ?></td>
<td><?php echo htmlspecialchars($pedido['monto_total']); ?></td>
<td><?php echo htmlspecialchars($pedido['monto_debe']); ?></td>
<td><?php echo htmlspecialchars($pedido['numero_operacion'] ?? 'N/A'); ?></td>
<td><?php echo htmlspecialchars($pedido['banco'] ?? 'N/A'); ?></td> <td><?php echo htmlspecialchars($pedido['banco'] ?? 'N/A'); ?></td>
<td <?php if (in_array($user_role, ['Administrador', 'personal', 'Verificador de Pagos', 'Control Logistico', 'Logistica']) || strpos($user_role, 'Asesor') !== false) { echo 'class="editable-recojo" data-id="'.$pedido['id'].'" title="Doble clic para editar"'; } ?>> <td <?php if (in_array($user_role, ['Administrador', 'personal', 'Verificador de Pagos', 'Control Logistico', 'Logistica']) || strpos($user_role, 'Asesor') !== false) { echo 'class="editable-recojo" data-id="'.$pedido['id'].'" title="Doble clic para editar"'; } ?>>
<?php echo !empty($pedido['fecha_recojo']) ? htmlspecialchars($pedido['fecha_recojo']) : 'N/A'; ?> <?php echo !empty($pedido['fecha_recojo']) ? htmlspecialchars($pedido['fecha_recojo']) : 'N/A'; ?>

View File

@ -0,0 +1,12 @@
CREATE TABLE IF NOT EXISTS operaciones_provincia (
id INT AUTO_INCREMENT PRIMARY KEY,
cliente VARCHAR(255),
celular VARCHAR(50),
producto VARCHAR(255),
monto_total DECIMAL(10, 2) DEFAULT 0.00,
monto_debe DECIMAL(10, 2) DEFAULT 0.00,
nro_operacion VARCHAR(100),
banco VARCHAR(100),
fecha_completado DATE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

View File

@ -0,0 +1,2 @@
ALTER TABLE operaciones_provincia ADD COLUMN pedido_id INT NULL;
ALTER TABLE operaciones_provincia ADD CONSTRAINT fk_operaciones_pedido FOREIGN KEY (pedido_id) REFERENCES pedidos(id) ON DELETE SET NULL;

View File

@ -0,0 +1,2 @@
-- Migration: Change fecha_completado to DATETIME in operaciones_provincia
ALTER TABLE operaciones_provincia MODIFY COLUMN fecha_completado DATETIME;

View File

@ -50,6 +50,12 @@ $navItems = [
'text' => 'Pedidos Completados', 'text' => 'Pedidos Completados',
'roles' => ['Administrador', 'admin', 'Asesor', 'Control Logistico', 'Soporte Logistico', 'Verificador de Pagos'] 'roles' => ['Administrador', 'admin', 'Asesor', 'Control Logistico', 'Soporte Logistico', 'Verificador de Pagos']
], ],
'operaciones_provincia' => [
'url' => 'operaciones_provincia.php',
'icon' => 'fa-map-location-dot',
'text' => 'Operaciones De provincia',
'roles' => ['Administrador', 'admin']
],
'listos_para_recojo' => [ 'listos_para_recojo' => [
'url' => 'listos_para_recojo.php', 'url' => 'listos_para_recojo.php',
'icon' => 'fa-box-open', 'icon' => 'fa-box-open',

293
operaciones_provincia.php Normal file
View File

@ -0,0 +1,293 @@
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
header('Location: login.php');
exit;
}
$user_role = $_SESSION['user_role'] ?? '';
if ($user_role !== 'Administrador' && $user_role !== 'admin') {
header('Location: dashboard.php');
exit;
}
require_once 'db/config.php';
$pageTitle = "Operaciones De provincia";
include 'layout_header.php';
$pdo = db();
// Filter by date
$selected_date = $_GET['fecha'] ?? date('Y-m-d');
// Fetch data from DB for the selected date
$operaciones = [];
$total_recaudacion = 0;
try {
$stmt = $pdo->prepare("SELECT * FROM operaciones_provincia WHERE DATE(fecha_completado) = ? ORDER BY fecha_completado DESC");
$stmt->execute([$selected_date]);
$operaciones = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($operaciones as $op) {
$total_recaudacion += (float)($op['monto_debe'] ?? 0);
}
} catch (PDOException $e) {
// Handle error
}
?>
<style>
.table thead th {
background-color: #337ab7;
color: #ffffff;
font-weight: 600;
position: sticky;
top: 0;
z-index: 10;
}
.table td[contenteditable="true"]:focus {
background-color: #fff3cd;
outline: 2px solid #337ab7;
}
.btn-add {
margin-bottom: 15px;
}
.summary-card {
background: linear-gradient(135deg, #198754 0%, #146c43 100%);
color: white;
border: none;
border-radius: 15px;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
</style>
<div class="container-fluid mt-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>Operaciones De provincia</h2>
<div class="d-flex gap-3 align-items-center">
<form method="GET" class="d-flex align-items-center gap-2">
<label for="fecha" class="mb-0 fw-bold">Fecha:</label>
<input type="date" name="fecha" id="fecha" class="form-control" value="<?php echo $selected_date; ?>" onchange="this.form.submit()">
</form>
<button id="addRow" class="btn btn-success">
<i class="fas fa-plus"></i> Agregar Fila
</button>
</div>
</div>
<div class="row mb-4">
<div class="col-md-4">
<div class="card summary-card">
<div class="card-body">
<h5 class="card-title opacity-75">Recaudación del Día</h5>
<h2 class="mb-0 fw-bold">S/ <?php echo number_format($total_recaudacion, 2); ?></h2>
<p class="mb-0 mt-2 small opacity-75">
<i class="fas fa-calendar-alt me-1"></i>
<?php echo date('d/m/Y', strtotime($selected_date)); ?>
</p>
</div>
</div>
</div>
</div>
<div class="card shadow-sm">
<div class="card-body p-0">
<div class="table-responsive" style="max-height: 65vh; overflow-y: auto;">
<table class="table table-bordered table-striped table-hover mb-0" id="operacionesTable">
<thead>
<tr>
<th>ID</th>
<th>Cliente</th>
<th>Celular</th>
<th>Producto</th>
<th>Monto Total</th>
<th>Monto que debe</th>
<th>Nro. Operación</th>
<th>Banco</th>
<th>Fecha Completado</th>
<th>Acciones</th>
</tr>
</thead>
<tbody>
<?php if (empty($operaciones)): ?>
<tr class="no-data">
<td colspan="10" class="text-center py-4 text-muted">No hay operaciones registradas para esta fecha.</td>
</tr>
<?php else: ?>
<?php foreach ($operaciones as $op): ?>
<tr data-id="<?php echo $op['id']; ?>">
<td><?php echo $op['id']; ?></td>
<td contenteditable="true" data-column="cliente"><?php echo htmlspecialchars($op['cliente'] ?? ''); ?></td>
<td contenteditable="true" data-column="celular"><?php echo htmlspecialchars($op['celular'] ?? ''); ?></td>
<td contenteditable="true" data-column="producto"><?php echo htmlspecialchars($op['producto'] ?? ''); ?></td>
<td contenteditable="true" data-column="monto_total"><?php echo htmlspecialchars($op['monto_total'] ?? '0.00'); ?></td>
<td contenteditable="true" data-column="monto_debe"><?php echo htmlspecialchars($op['monto_debe'] ?? '0.00'); ?></td>
<td contenteditable="true" data-column="nro_operacion"><?php echo htmlspecialchars($op['nro_operacion'] ?? ''); ?></td>
<td contenteditable="true" data-column="banco"><?php echo htmlspecialchars($op['banco'] ?? ''); ?></td>
<td contenteditable="true" data-column="fecha_completado"><?php
if (!empty($op['fecha_completado'])) {
try {
$date = new DateTime($op['fecha_completado']);
echo htmlspecialchars($date->format('d/m/Y H:i:s'));
} catch (Exception $e) {
echo htmlspecialchars($op['fecha_completado']);
}
}
?></td>
<td class="text-center">
<button class="btn btn-outline-danger btn-sm delete-row">
<i class="fas fa-trash"></i>
</button>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const table = document.getElementById('operacionesTable');
const tbody = table.querySelector('tbody');
const addRowBtn = document.getElementById('addRow');
const selectedDate = "<?php echo $selected_date; ?>";
function updateSummary() {
let total = 0;
table.querySelectorAll('tbody tr:not(.no-data)').forEach(row => {
const val = parseFloat(row.querySelector('[data-column="monto_debe"]').textContent.replace(/[^0-9.-]/g, '')) || 0;
total += val;
});
document.querySelector('.summary-card h2').textContent = 'S/ ' + total.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
}
// Add new row
addRowBtn.addEventListener('click', function() {
const noDataRow = tbody.querySelector('.no-data');
if (noDataRow) noDataRow.remove();
const now = new Date();
const day = String(now.getDate()).padStart(2, '0');
const month = String(now.getMonth() + 1).padStart(2, '0');
const year = now.getFullYear();
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
const currentDateTime = `${day}/${month}/${year} ${hours}:${minutes}:${seconds}`;
fetch('save_operaciones_provincia.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'create' })
})
.then(response => response.json())
.then(data => {
if (data.success) {
const tr = document.createElement('tr');
tr.dataset.id = data.id;
tr.innerHTML = `
<td>${data.id}</td>
<td contenteditable="true" data-column="cliente"></td>
<td contenteditable="true" data-column="celular"></td>
<td contenteditable="true" data-column="producto"></td>
<td contenteditable="true" data-column="monto_total">0.00</td>
<td contenteditable="true" data-column="monto_debe">0.00</td>
<td contenteditable="true" data-column="nro_operacion"></td>
<td contenteditable="true" data-column="banco"></td>
<td contenteditable="true" data-column="fecha_completado">${currentDateTime}</td>
<td class="text-center">
<button class="btn btn-outline-danger btn-sm delete-row">
<i class="fas fa-trash"></i>
</button>
</td>
`;
tbody.insertBefore(tr, tbody.firstChild);
// Set initial date
fetch('save_operaciones_provincia.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'update', id: data.id, column: 'fecha_completado', value: currentDateTime })
});
tr.querySelector('[data-column="cliente"]').focus();
}
});
});
// Edit cell
table.addEventListener('blur', function(e) {
if (e.target.hasAttribute('contenteditable')) {
const cell = e.target;
const row = cell.closest('tr');
const id = row.dataset.id;
const column = cell.dataset.column;
let value = cell.textContent.trim();
// Basic numeric formatting for monto columns
if (column === 'monto_total' || column === 'monto_debe') {
let num = parseFloat(value.replace(/[^0-9.-]/g, ''));
if (isNaN(num)) num = 0;
value = num.toFixed(2);
cell.textContent = value;
updateSummary();
}
fetch('save_operaciones_provincia.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'update', id: id, column: column, value: value })
})
.then(response => response.json())
.then(data => {
if (!data.success) {
alert('Error al guardar: ' + data.message);
}
});
}
}, true);
// Delete row
table.addEventListener('click', function(e) {
if (e.target.closest('.delete-row')) {
if (confirm('¿Estás seguro de eliminar esta fila?')) {
const row = e.target.closest('tr');
const id = row.dataset.id;
fetch('save_operaciones_provincia.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action: 'delete', id: id })
})
.then(response => response.json())
.then(data => {
if (data.success) {
row.remove();
updateSummary();
if (tbody.children.length === 0) {
tbody.innerHTML = '<tr class="no-data"><td colspan="10" class="text-center py-4 text-muted">No hay operaciones registradas para esta fecha.</td></tr>';
}
} else {
alert('Error al eliminar: ' + data.message);
}
});
}
}
});
// Handle Enter key
table.addEventListener('keydown', function(e) {
if (e.key === 'Enter' && e.target.hasAttribute('contenteditable')) {
e.preventDefault();
e.target.blur();
}
});
});
</script>
<?php include 'layout_footer.php'; ?>

View File

@ -0,0 +1,78 @@
<?php
session_start();
if (!isset($_SESSION['user_id'])) {
http_response_code(403);
echo json_encode(['success' => false, 'message' => 'No autorizado']);
exit;
}
$user_role = $_SESSION['user_role'] ?? '';
if ($user_role !== 'Administrador' && $user_role !== 'admin') {
http_response_code(403);
echo json_encode(['success' => false, 'message' => 'No autorizado']);
exit;
}
require_once 'db/config.php';
$data = json_decode(file_get_contents('php://input'), true);
if (!$data) {
http_response_code(400);
echo json_encode(['success' => false, 'message' => 'No se recibieron datos']);
exit;
}
$action = $data['action'] ?? '';
$pdo = db();
try {
if ($action === 'create') {
$stmt = $pdo->prepare("INSERT INTO operaciones_provincia (cliente) VALUES ('')");
$stmt->execute();
echo json_encode(['success' => true, 'id' => $pdo->lastInsertId()]);
} elseif ($action === 'update') {
$id = $data['id'];
$column = $data['column'];
$value = $data['value'];
$allowed_columns = [
'cliente', 'celular', 'producto', 'monto_total',
'monto_debe', 'nro_operacion', 'banco', 'fecha_completado'
];
if (!in_array($column, $allowed_columns)) {
throw new Exception("Columna no permitida");
}
// Convert date format if column is fecha_completado
if ($column === 'fecha_completado' && !empty($value)) {
// Try to parse d/m/Y H:i:s
$d = DateTime::createFromFormat('d/m/Y H:i:s', $value);
if ($d && $d->format('d/m/Y H:i:s') === $value) {
$value = $d->format('Y-m-d H:i:s');
} else {
// Try d/m/Y
$d = DateTime::createFromFormat('d/m/Y', $value);
if ($d && $d->format('d/m/Y') === $value) {
$value = $d->format('Y-m-d 00:00:00');
}
}
}
$stmt = $pdo->prepare("UPDATE operaciones_provincia SET $column = :value WHERE id = :id");
$stmt->execute(['value' => $value, 'id' => $id]);
echo json_encode(['success' => true]);
} elseif ($action === 'delete') {
$id = $data['id'];
$stmt = $pdo->prepare("DELETE FROM operaciones_provincia WHERE id = :id");
$stmt->execute(['id' => $id]);
echo json_encode(['success' => true]);
} else {
throw new Exception("Acción no válida");
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
?>

View File

@ -178,6 +178,26 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$current_fecha_completado = $stmt_check->fetchColumn(); $current_fecha_completado = $stmt_check->fetchColumn();
if ($current_fecha_completado === null) { if ($current_fecha_completado === null) {
$sql_parts[] = "fecha_completado = NOW()"; $sql_parts[] = "fecha_completado = NOW()";
// --- NEW: Insert into operaciones_provincia ---
$stmt_p = $pdo->prepare("SELECT * FROM pedidos WHERE id = ?");
$stmt_p->execute([$id]);
$p_data = $stmt_p->fetch(PDO::FETCH_ASSOC);
if ($p_data) {
$stmt_op = $pdo->prepare("INSERT INTO operaciones_provincia (pedido_id, cliente, celular, producto, monto_total, monto_debe, nro_operacion, banco, fecha_completado) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())");
$stmt_op->execute([
$id,
$p_data['nombre_completo'],
$p_data['celular'],
$p_data['producto'],
$p_data['monto_total'],
$p_data['monto_debe'],
$numero_operacion,
$banco
]);
}
// --- End of NEW ---
} }
} }
@ -209,6 +229,23 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$sql = "INSERT INTO pedidos ($columns_sql) VALUES ($values_sql)"; $sql = "INSERT INTO pedidos ($columns_sql) VALUES ($values_sql)";
$stmt = $pdo->prepare($sql); $stmt = $pdo->prepare($sql);
$stmt->execute($params); $stmt->execute($params);
$new_id = $pdo->lastInsertId();
// --- NEW: Insert into operaciones_provincia if completed ---
if (in_array($estado, $completed_states)) {
$stmt_op = $pdo->prepare("INSERT INTO operaciones_provincia (pedido_id, cliente, celular, producto, monto_total, monto_debe, nro_operacion, banco, fecha_completado) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())");
$stmt_op->execute([
$new_id,
$nombre_completo,
$celular,
$producto,
$monto_total,
$monto_debe,
$numero_operacion,
$banco
]);
}
// --- End of NEW ---
} }
if (isset($_POST['id']) && !empty($_POST['id'])) { if (isset($_POST['id']) && !empty($_POST['id'])) {