Autosave: 20260518-233649
This commit is contained in:
parent
bbd26aa303
commit
a8d2f9cb0a
@ -116,7 +116,7 @@ body {
|
||||
body.sidebar-active .content {
|
||||
/* Don't push content, but apply a visual effect */
|
||||
filter: blur(3px) brightness(0.6);
|
||||
pointer-events: none; /* Prevent interaction with content when sidebar is open */
|
||||
/* pointer-events: none; REMOVED to allow interaction even if sidebar is active */
|
||||
}
|
||||
|
||||
/* The body itself gets an overlay to darken it */
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
<?php
|
||||
header("Location: calculo_costos_v3.php");
|
||||
exit();
|
||||
$pageTitle = "Cálculo de Costos V2";
|
||||
include 'db/config.php';
|
||||
include 'layout_header.php';
|
||||
@ -24,210 +26,244 @@ $costos = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
<style>
|
||||
.table-v2 {
|
||||
font-size: 0.85rem;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 5px;
|
||||
}
|
||||
.table-v2 th {
|
||||
background-color: #f1f3f5;
|
||||
border-bottom: 2px solid #dee2e6;
|
||||
white-space: nowrap;
|
||||
padding: 12px 8px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
.table-v2 td {
|
||||
vertical-align: middle;
|
||||
padding: 4px;
|
||||
padding: 8px 4px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.input-cell {
|
||||
width: 100%;
|
||||
min-width: 80px;
|
||||
padding: 6px;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 4px;
|
||||
min-width: 85px;
|
||||
padding: 8px;
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 6px;
|
||||
text-align: center;
|
||||
font-size: 0.85rem;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s;
|
||||
cursor: text !important;
|
||||
pointer-events: auto !important;
|
||||
}
|
||||
.input-cell:focus {
|
||||
border-color: #0d6efd;
|
||||
box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25);
|
||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.15);
|
||||
outline: 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
.input-cell:hover {
|
||||
border-color: #adb5bd;
|
||||
}
|
||||
.input-cell.saving {
|
||||
background-color: #fff3cd;
|
||||
border-color: #ffc107;
|
||||
background-color: #fff3cd !important;
|
||||
border-color: #ffc107 !important;
|
||||
}
|
||||
.input-cell.saved {
|
||||
background-color: #d1e7dd;
|
||||
border-color: #198754;
|
||||
background-color: #d1e7dd !important;
|
||||
border-color: #198754 !important;
|
||||
}
|
||||
.recaudo-v2 {
|
||||
background-color: #f8f9fa;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
min-width: 90px;
|
||||
transition: all 0.3s;
|
||||
padding: 10px;
|
||||
border-radius: 6px;
|
||||
min-width: 100px;
|
||||
border: 1px solid #dee2e6;
|
||||
}
|
||||
.img-v2 {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
object-fit: cover;
|
||||
border-radius: 4px;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
.btn-save-row {
|
||||
padding: 6px 12px;
|
||||
.btn-action {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.editable-label {
|
||||
font-size: 0.7rem;
|
||||
color: #6c757d;
|
||||
display: block;
|
||||
margin-bottom: 2px;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div>
|
||||
<h2 class="mb-0">Cálculo de Costos <span class="badge bg-warning text-dark">Versión 2</span></h2>
|
||||
<p class="text-muted">Edición directa mediante cuadros de texto. Escribe y presiona "Guardar".</p>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#modalNuevoV2">
|
||||
<i class="fas fa-plus me-2"></i> Nuevo Producto
|
||||
</button>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center mb-4 mt-2">
|
||||
<div>
|
||||
<p class="text-muted mb-0">Edición directa: Escribe en los cuadros y los cambios se guardarán al salir del cuadro.</p>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<button type="button" class="btn btn-outline-secondary" onclick="location.reload()">
|
||||
<i class="fas fa-sync-alt"></i> Actualizar Todo
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary shadow-sm" data-bs-toggle="modal" data-bs-target="#modalNuevoV2">
|
||||
<i class="fas fa-plus me-2"></i> Nuevo Producto
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (isset($_GET['success'])): ?>
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
¡Cambios guardados correctamente!
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if (isset($_GET['success'])): ?>
|
||||
<div class="alert alert-success alert-dismissible fade show shadow-sm" role="alert">
|
||||
<i class="fas fa-check-circle me-2"></i> ¡Operación realizada con éxito!
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-v2 mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">Orden</th>
|
||||
<th>Producto</th>
|
||||
<th class="text-center">Imagen</th>
|
||||
<th class="text-center">Costo Prod.</th>
|
||||
<th class="text-center">Film</th>
|
||||
<th class="text-center">Asesora</th>
|
||||
<th class="text-center">Delivery</th>
|
||||
<th class="text-center">Publicidad</th>
|
||||
<th class="text-center bg-light">Inversión Total</th>
|
||||
<th class="text-center">Promo 1</th>
|
||||
<th class="text-center">Recaudo 1</th>
|
||||
<th class="text-center">Promo 2</th>
|
||||
<th class="text-center">Recaudo 2</th>
|
||||
<th class="text-center">Promo 3</th>
|
||||
<th class="text-center">Recaudo 3</th>
|
||||
<th class="text-center">Acción</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($costos as $c): ?>
|
||||
<?php
|
||||
$inversion_total = ($c['costo_producto'] ?? 0) +
|
||||
($c['costo_fijo_film'] ?? 0) +
|
||||
($c['comision_asesora'] ?? 0) +
|
||||
($c['delivery'] ?? 0) +
|
||||
($c['costo_publicitario'] ?? 0);
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive" style="max-height: 70vh;">
|
||||
<table class="table table-v2 mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">Orden</th>
|
||||
<th>Producto</th>
|
||||
<th class="text-center">Imagen</th>
|
||||
<th class="text-center">Costo Prod.</th>
|
||||
<th class="text-center">Film</th>
|
||||
<th class="text-center">Asesora</th>
|
||||
<th class="text-center">Delivery</th>
|
||||
<th class="text-center">Publicidad</th>
|
||||
<th class="text-center bg-light">Inversión Total</th>
|
||||
<th class="text-center">Promo 1</th>
|
||||
<th class="text-center">Recaudo 1</th>
|
||||
<th class="text-center">Promo 2</th>
|
||||
<th class="text-center">Recaudo 2</th>
|
||||
<th class="text-center">Promo 3</th>
|
||||
<th class="text-center">Recaudo 3</th>
|
||||
<th class="text-center">Acción</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($costos as $c): ?>
|
||||
<?php
|
||||
$inversion_total = ($c['costo_producto'] ?? 0) +
|
||||
($c['costo_fijo_film'] ?? 0) +
|
||||
($c['comision_asesora'] ?? 0) +
|
||||
($c['delivery'] ?? 0) +
|
||||
($c['costo_publicitario'] ?? 0);
|
||||
|
||||
function getVal($promo) {
|
||||
preg_match('/[\d.]+/', $promo, $matches);
|
||||
return isset($matches[0]) ? floatval($matches[0]) : 0;
|
||||
}
|
||||
function getVal($promo) {
|
||||
if (empty($promo)) return 0;
|
||||
preg_match('/[\d.]+/', $promo, $matches);
|
||||
return isset($matches[0]) ? floatval($matches[0]) : 0;
|
||||
}
|
||||
|
||||
$p1 = getVal($c['promo_1']);
|
||||
$p2 = getVal($c['promo_2']);
|
||||
$p3 = getVal($c['promo_3']);
|
||||
$p1 = getVal($c['promo_1']);
|
||||
$p2 = getVal($c['promo_2']);
|
||||
$p3 = getVal($c['promo_3']);
|
||||
|
||||
$r1 = $p1 > 0 ? $p1 - $inversion_total : null;
|
||||
$r2 = $p2 > 0 ? $p2 - $inversion_total : null;
|
||||
$r3 = $p3 > 0 ? $p3 - $inversion_total : null;
|
||||
?>
|
||||
<tr id="row-<?php echo $c['id']; ?>" data-id="<?php echo $c['id']; ?>">
|
||||
<td class="text-center fw-bold"><?php echo $c['orden']; ?></td>
|
||||
<td style="max-width: 150px;" class="text-truncate" title="<?php echo htmlspecialchars($c['nombre_producto']); ?>">
|
||||
$r1 = $p1 > 0 ? $p1 - $inversion_total : null;
|
||||
$r2 = $p2 > 0 ? $p2 - $inversion_total : null;
|
||||
$r3 = $p3 > 0 ? $p3 - $inversion_total : null;
|
||||
?>
|
||||
<tr id="row-<?php echo $c['id']; ?>" data-id="<?php echo $c['id']; ?>">
|
||||
<td class="text-center fw-bold text-primary"><?php echo $c['orden']; ?></td>
|
||||
<td style="max-width: 140px;">
|
||||
<div class="text-truncate fw-bold" title="<?php echo htmlspecialchars($c['nombre_producto']); ?>">
|
||||
<?php echo htmlspecialchars($c['nombre_producto'] ?: 'General'); ?>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php if ($c['foto_producto']): ?>
|
||||
<img src="<?php echo $c['foto_producto']; ?>" class="img-v2">
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><input type="number" step="0.01" class="input-cell" data-field="costo_producto" value="<?php echo $c['costo_producto']; ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'costo_producto', this.value)"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell" data-field="costo_fijo_film" value="<?php echo $c['costo_fijo_film']; ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'costo_fijo_film', this.value)"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell" data-field="comision_asesora" value="<?php echo $c['comision_asesora']; ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'comision_asesora', this.value)"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell" data-field="delivery" value="<?php echo $c['delivery']; ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'delivery', this.value)"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell" data-field="costo_publicitario" value="<?php echo $c['costo_publicitario']; ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'costo_publicitario', this.value)"></td>
|
||||
<td class="text-center">
|
||||
<div class="recaudo-v2 bg-light fw-bold" id="total-<?php echo $c['id']; ?>">
|
||||
S/ <?php echo number_format($inversion_total, 2); ?>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php if ($c['foto_producto']): ?>
|
||||
<img src="<?php echo $c['foto_producto']; ?>" class="img-v2">
|
||||
<?php else: ?>
|
||||
<div class="bg-light rounded d-flex align-items-center justify-content-center" style="width:45px; height:45px;">
|
||||
<i class="fas fa-image text-muted"></i>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td><input type="text" class="input-cell" data-field="promo_1" value="<?php echo htmlspecialchars($c['promo_1']); ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'promo_1', this.value)"></td>
|
||||
<td><div class="recaudo-v2 recaudo-1 <?php echo $r1 >= 0 ? 'text-success' : 'text-danger'; ?>" id="r1-<?php echo $c['id']; ?>"><?php echo $r1 !== null ? 'S/ '.number_format($r1, 2) : '-'; ?></div></td>
|
||||
|
||||
<td><input type="text" class="input-cell" data-field="promo_2" value="<?php echo htmlspecialchars($c['promo_2']); ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'promo_2', this.value)"></td>
|
||||
<td><div class="recaudo-v2 recaudo-2 <?php echo $r2 >= 0 ? 'text-success' : 'text-danger'; ?>" id="r2-<?php echo $c['id']; ?>"><?php echo $r2 !== null ? 'S/ '.number_format($r2, 2) : '-'; ?></div></td>
|
||||
|
||||
<td><input type="text" class="input-cell" data-field="promo_3" value="<?php echo htmlspecialchars($c['promo_3']); ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'promo_3', this.value)"></td>
|
||||
<td><div class="recaudo-v2 recaudo-3 <?php echo $r3 >= 0 ? 'text-success' : 'text-danger'; ?>" id="r3-<?php echo $c['id']; ?>"><?php echo $r3 !== null ? 'S/ '.number_format($r3, 2) : '-'; ?></div></td>
|
||||
|
||||
<td class="text-center">
|
||||
<div class="d-flex gap-1">
|
||||
<button class="btn btn-success btn-sm btn-save-row" onclick="location.reload()" title="Refrescar cálculos">
|
||||
<i class="fas fa-sync-alt"></i>
|
||||
</button>
|
||||
<button class="btn btn-danger btn-sm" onclick="eliminarRow(<?php echo $c['id']; ?>)">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><input type="number" step="0.01" class="input-cell" data-field="costo_producto" value="<?php echo $c['costo_producto']; ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'costo_producto', this.value)"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell" data-field="costo_fijo_film" value="<?php echo $c['costo_fijo_film']; ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'costo_fijo_film', this.value)"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell" data-field="comision_asesora" value="<?php echo $c['comision_asesora']; ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'comision_asesora', this.value)"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell" data-field="delivery" value="<?php echo $c['delivery']; ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'delivery', this.value)"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell" data-field="costo_publicitario" value="<?php echo $c['costo_publicitario']; ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'costo_publicitario', this.value)"></td>
|
||||
<td class="text-center">
|
||||
<div class="recaudo-v2 bg-light fw-bold text-dark" id="total-<?php echo $c['id']; ?>">
|
||||
S/ <?php echo number_format($inversion_total, 2); ?>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td><input type="text" class="input-cell" data-field="promo_1" value="<?php echo htmlspecialchars($c['promo_1']); ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'promo_1', this.value)"></td>
|
||||
<td><div class="recaudo-v2 recaudo-1 <?php echo $r1 >= 0 ? 'text-success' : 'text-danger'; ?>" id="r1-<?php echo $c['id']; ?>"><?php echo $r1 !== null ? 'S/ '.number_format($r1, 2) : '-'; ?></div></td>
|
||||
|
||||
<td><input type="text" class="input-cell" data-field="promo_2" value="<?php echo htmlspecialchars($c['promo_2']); ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'promo_2', this.value)"></td>
|
||||
<td><div class="recaudo-v2 recaudo-2 <?php echo $r2 >= 0 ? 'text-success' : 'text-danger'; ?>" id="r2-<?php echo $c['id']; ?>"><?php echo $r2 !== null ? 'S/ '.number_format($r2, 2) : '-'; ?></div></td>
|
||||
|
||||
<td><input type="text" class="input-cell" data-field="promo_3" value="<?php echo htmlspecialchars($c['promo_3']); ?>" onchange="updateRow(<?php echo $c['id']; ?>, 'promo_3', this.value)"></td>
|
||||
<td><div class="recaudo-v2 recaudo-3 <?php echo $r3 >= 0 ? 'text-success' : 'text-danger'; ?>" id="r3-<?php echo $c['id']; ?>"><?php echo $r3 !== null ? 'S/ '.number_format($r3, 2) : '-'; ?></div></td>
|
||||
|
||||
<td class="text-center">
|
||||
<button class="btn btn-danger btn-action" onclick="eliminarRow(<?php echo $c['id']; ?>)" title="Eliminar">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Nuevo -->
|
||||
<div class="modal fade" id="modalNuevoV2" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal fade" id="modalNuevoV2" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<form action="save_marketing_video.php" method="POST" enctype="multipart/form-data">
|
||||
<input type="hidden" name="redirect" value="calculo_costos_v2.php?success=1">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Nuevo Producto</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
<div class="modal-header bg-primary text-white">
|
||||
<h5 class="modal-title"><i class="fas fa-plus-circle me-2"></i> Nuevo Producto para Costos</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="modal-body p-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Producto</label>
|
||||
<select name="producto_id" id="select_producto_nuevo" class="form-select" required onchange="fetchProductCost(this.value)">
|
||||
<label class="form-label fw-bold">Seleccionar Producto</label>
|
||||
<select name="producto_id" id="select_producto_nuevo" class="form-select form-select-lg" required onchange="fetchProductCost(this.value)">
|
||||
<option value="">Seleccionar...</option>
|
||||
<?php foreach ($productos_select as $p): ?>
|
||||
<option value="<?php echo $p['id']; ?>"><?php echo htmlspecialchars($p['nombre']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Costo del Producto (S/)</label>
|
||||
<input type="number" name="costo_producto" id="costo_producto_nuevo" class="form-control" step="0.01" placeholder="0.00">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-bold">Costo Base (S/)</label>
|
||||
<input type="number" name="costo_producto" id="costo_producto_nuevo" class="form-control" step="0.01" placeholder="0.00">
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-bold">Orden de Lista</label>
|
||||
<input type="number" name="orden" class="form-control" value="1">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Orden</label>
|
||||
<input type="number" name="orden" class="form-control" value="1">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Imagen</label>
|
||||
<div class="mb-0">
|
||||
<label class="form-label fw-bold">Imagen del Producto</label>
|
||||
<input type="file" name="foto_producto" class="form-control">
|
||||
<small class="text-muted">Opcional. Si no se sube, se usará la del producto.</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cerrar</button>
|
||||
<button type="submit" class="btn btn-primary">Guardar</button>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-primary px-4">Crear Registro</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -235,6 +271,8 @@ $costos = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
</div>
|
||||
|
||||
<script>
|
||||
console.log("Script de Cálculo de Costos V2 cargado");
|
||||
|
||||
function fetchProductCost(productId) {
|
||||
if (!productId) return;
|
||||
|
||||
@ -252,6 +290,8 @@ function updateRow(id, field, value) {
|
||||
const row = document.getElementById(`row-${id}`);
|
||||
const input = row.querySelector(`[data-field="${field}"]`);
|
||||
|
||||
if (!input) return;
|
||||
|
||||
input.classList.add('saving');
|
||||
console.log(`Actualizando ${field} para ID ${id} con valor ${value}`);
|
||||
|
||||
@ -265,54 +305,64 @@ function updateRow(id, field, value) {
|
||||
input.classList.remove('saving');
|
||||
if (data.success) {
|
||||
input.classList.add('saved');
|
||||
setTimeout(() => input.classList.remove('saved'), 1000);
|
||||
setTimeout(() => input.classList.remove('saved'), 1500);
|
||||
|
||||
// Recalcular todo en la fila
|
||||
recalculateRow(id);
|
||||
} else {
|
||||
alert('Error al guardar: ' + data.error);
|
||||
alert('Error al guardar: ' + (data.error || 'Error desconocido'));
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
input.classList.remove('saving');
|
||||
console.error('Error:', error);
|
||||
alert('Error de conexión');
|
||||
alert('Error de conexión al servidor');
|
||||
});
|
||||
}
|
||||
|
||||
function recalculateRow(id) {
|
||||
const row = document.getElementById(`row-${id}`);
|
||||
if (!row) return;
|
||||
|
||||
const fields = ['costo_producto', 'costo_fijo_film', 'comision_asesora', 'delivery', 'costo_publicitario'];
|
||||
|
||||
let total = 0;
|
||||
fields.forEach(f => {
|
||||
const val = parseFloat(row.querySelector(`[data-field="${f}"]`).value) || 0;
|
||||
total += val;
|
||||
const el = row.querySelector(`[data-field="${f}"]`);
|
||||
if (el) {
|
||||
total += parseFloat(el.value) || 0;
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById(`total-${id}`).innerText = 'S/ ' + total.toFixed(2);
|
||||
const totalEl = document.getElementById(`total-${id}`);
|
||||
if (totalEl) {
|
||||
totalEl.innerText = 'S/ ' + total.toFixed(2);
|
||||
}
|
||||
|
||||
// Recalcular recaudos
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
const promoVal = row.querySelector(`[data-field="promo_${i}"]`).value;
|
||||
const promoEl = row.querySelector(`[data-field="promo_${i}"]`);
|
||||
const recaudoEl = document.getElementById(`r${i}-${id}`);
|
||||
|
||||
const match = promoVal.match(/[\d.]+/);
|
||||
const pVal = match ? parseFloat(match[0]) : 0;
|
||||
|
||||
if (pVal > 0) {
|
||||
const recaudo = pVal - total;
|
||||
recaudoEl.innerText = 'S/ ' + recaudo.toFixed(2);
|
||||
recaudoEl.className = 'recaudo-v2 ' + (recaudo >= 0 ? 'text-success' : 'text-danger');
|
||||
} else {
|
||||
recaudoEl.innerText = '-';
|
||||
recaudoEl.className = 'recaudo-v2 text-muted';
|
||||
if (promoEl && recaudoEl) {
|
||||
const promoVal = promoEl.value;
|
||||
const match = promoVal.match(/[\d.]+/);
|
||||
const pVal = match ? parseFloat(match[0]) : 0;
|
||||
|
||||
if (pVal > 0) {
|
||||
const recaudo = pVal - total;
|
||||
recaudoEl.innerText = 'S/ ' + recaudo.toFixed(2);
|
||||
recaudoEl.className = 'recaudo-v2 ' + (recaudo >= 0 ? 'text-success' : 'text-danger');
|
||||
} else {
|
||||
recaudoEl.innerText = '-';
|
||||
recaudoEl.className = 'recaudo-v2 text-muted';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function eliminarRow(id) {
|
||||
if (confirm('¿Eliminar este producto?')) {
|
||||
if (confirm('¿Estás seguro de que deseas eliminar este registro de costos?')) {
|
||||
window.location.href = 'delete_marketing_video.php?id=' + id + '&redirect=calculo_costos_v2.php';
|
||||
}
|
||||
}
|
||||
|
||||
398
calculo_costos_v3.php
Normal file
398
calculo_costos_v3.php
Normal file
@ -0,0 +1,398 @@
|
||||
<?php
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
if (!isset($_SESSION['user_role']) || !in_array($_SESSION['user_role'], ['Administrador', 'admin'])) {
|
||||
header('Location: dashboard.php');
|
||||
exit();
|
||||
}
|
||||
$pageTitle = "Cálculo de Costos V3";
|
||||
include 'db/config.php';
|
||||
include 'layout_header.php';
|
||||
|
||||
$db = db();
|
||||
|
||||
// Obtener productos para el select del modal
|
||||
$stmt_products = $db->query("SELECT id, nombre FROM products ORDER BY nombre ASC");
|
||||
$productos_select = $stmt_products->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Obtener videos y sus costos asociados de las tablas V3
|
||||
$stmt = $db->query("SELECT mv.id, mv.orden, mv.foto_producto, p.nombre as nombre_producto,
|
||||
mc.costo_producto, mc.costo_fijo_film, mc.comision_asesora,
|
||||
mc.delivery, mc.costo_publicitario, mc.inversion_total,
|
||||
mc.promo_1, mc.promo_2, mc.promo_3,
|
||||
mc.comision_asesora_provincia, mc.delivery_provincia
|
||||
FROM marketing_videos_v3 mv
|
||||
LEFT JOIN products p ON mv.producto_id = p.id
|
||||
LEFT JOIN marketing_costos_v3 mc ON mv.id = mc.video_id
|
||||
ORDER BY mv.orden ASC, mv.id DESC");
|
||||
$costos = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
?>
|
||||
|
||||
<style>
|
||||
.table-v3 {
|
||||
font-size: 0.8rem;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 5px;
|
||||
}
|
||||
.table-v3 th {
|
||||
background-color: #f8f9fa;
|
||||
border-bottom: 2px solid #dee2e6;
|
||||
white-space: nowrap;
|
||||
padding: 10px 5px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
.table-v3 td {
|
||||
vertical-align: middle;
|
||||
padding: 6px 3px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.input-cell {
|
||||
width: 100%;
|
||||
min-width: 70px;
|
||||
padding: 6px;
|
||||
border: 2px solid #e9ecef;
|
||||
border-radius: 6px;
|
||||
text-align: center;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.input-cell:focus {
|
||||
border-color: #0d6efd;
|
||||
box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.15);
|
||||
outline: 0;
|
||||
}
|
||||
.input-cell.saving { background-color: #fff3cd !important; border-color: #ffc107 !important; }
|
||||
.input-cell.saved { background-color: #d1e7dd !important; border-color: #198754 !important; }
|
||||
|
||||
.recaudo-v3 {
|
||||
background-color: #f8f9fa;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
padding: 6px 4px;
|
||||
border-radius: 6px;
|
||||
min-width: 85px;
|
||||
border: 1px solid #dee2e6;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.recaudo-label {
|
||||
font-size: 0.65rem;
|
||||
display: block;
|
||||
color: #6c757d;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
.img-v3 {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
object-fit: cover;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.btn-action {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
padding: 0;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.bg-provincia {
|
||||
background-color: #fff4e6 !important;
|
||||
}
|
||||
.header-provincia {
|
||||
background-color: #ffe8cc !important;
|
||||
color: #d9480f !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-4 mt-2">
|
||||
<div>
|
||||
<p class="text-muted mb-0">Versión V3: Tabla limpia e independiente. Los cambios se guardan automáticamente.</p>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<button type="button" class="btn btn-outline-secondary" onclick="location.reload()">
|
||||
<i class="fas fa-sync-alt"></i> Actualizar
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary shadow-sm" data-bs-toggle="modal" data-bs-target="#modalNuevoV3">
|
||||
<i class="fas fa-plus me-2"></i> Nuevo Producto
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (isset($_GET['success'])): ?>
|
||||
<div class="alert alert-success alert-dismissible fade show shadow-sm" role="alert">
|
||||
<i class="fas fa-check-circle me-2"></i> ¡Operación realizada con éxito!
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive" style="max-height: 70vh;">
|
||||
<table class="table table-v3 mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">Orden</th>
|
||||
<th>Producto</th>
|
||||
<th class="text-center">Imagen</th>
|
||||
<th class="text-center">Costo Prod.</th>
|
||||
<th class="text-center">Film</th>
|
||||
<th class="text-center">Asesora (L)</th>
|
||||
<th class="text-center header-provincia">Asesora (P)</th>
|
||||
<th class="text-center">Delivery (L)</th>
|
||||
<th class="text-center header-provincia">Delivery (P)</th>
|
||||
<th class="text-center">Publicidad</th>
|
||||
<th class="text-center">Promo 1</th>
|
||||
<th class="text-center">Recaudo 1</th>
|
||||
<th class="text-center">Promo 2</th>
|
||||
<th class="text-center">Recaudo 2</th>
|
||||
<th class="text-center">Promo 3</th>
|
||||
<th class="text-center">Recaudo 3</th>
|
||||
<th class="text-center">Acción</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($costos)): ?>
|
||||
<tr>
|
||||
<td colspan="17" class="text-center py-5 text-muted">
|
||||
<i class="fas fa-info-circle me-2"></i> No hay productos en esta lista. Haz clic en "Nuevo Producto" para empezar.
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<?php foreach ($costos as $c): ?>
|
||||
<?php
|
||||
$costo_prod = ($c['costo_producto'] ?? 0);
|
||||
$costo_film = ($c['costo_fijo_film'] ?? 0);
|
||||
$costo_asesora = ($c['comision_asesora'] ?? 0);
|
||||
$costo_asesora_p = ($c['comision_asesora_provincia'] ?? 0);
|
||||
$costo_delivery = ($c['delivery'] ?? 0);
|
||||
$costo_delivery_p = ($c['delivery_provincia'] ?? 0);
|
||||
$costo_publicidad = ($c['costo_publicitario'] ?? 0);
|
||||
|
||||
function getVal($promo) {
|
||||
if (empty($promo)) return 0;
|
||||
preg_match('/[\d.]+/', $promo, $matches);
|
||||
return isset($matches[0]) ? floatval($matches[0]) : 0;
|
||||
}
|
||||
|
||||
$p1 = getVal($c['promo_1']);
|
||||
$p2 = getVal($c['promo_2']);
|
||||
$p3 = getVal($c['promo_3']);
|
||||
|
||||
// Cálculos Local
|
||||
$r1_l = $p1 > 0 ? $p1 - ($costo_prod + $costo_film + $costo_asesora + $costo_delivery + $costo_publicidad) : null;
|
||||
$r2_l = $p2 > 0 ? $p2 - (($costo_prod + $costo_film) * 2 + $costo_asesora + $costo_delivery + $costo_publicidad) : null;
|
||||
$r3_l = $p3 > 0 ? $p3 - (($costo_prod + $costo_film) * 3 + $costo_asesora + $costo_delivery + $costo_publicidad) : null;
|
||||
|
||||
// Cálculos Provincia
|
||||
$r1_p = $p1 > 0 ? $p1 - ($costo_prod + $costo_film + $costo_asesora_p + $costo_delivery_p + $costo_publicidad) : null;
|
||||
$r2_p = $p2 > 0 ? $p2 - (($costo_prod + $costo_film) * 2 + $costo_asesora_p + $costo_delivery_p + $costo_publicidad) : null;
|
||||
$r3_p = $p3 > 0 ? $p3 - (($costo_prod + $costo_film) * 3 + $costo_asesora_p + $costo_delivery_p + $costo_publicidad) : null;
|
||||
?>
|
||||
<tr id="row-<?php echo $c['id']; ?>" data-id="<?php echo $c['id']; ?>">
|
||||
<td class="text-center fw-bold text-primary"><?php echo $c['orden']; ?></td>
|
||||
<td style="max-width: 120px;">
|
||||
<div class="text-truncate fw-bold" title="<?php echo htmlspecialchars($c['nombre_producto']); ?>">
|
||||
<?php echo htmlspecialchars($c['nombre_producto'] ?: 'General'); ?>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<?php if ($c['foto_producto']): ?>
|
||||
<img src="<?php echo $c['foto_producto']; ?>" class="img-v3">
|
||||
<?php else: ?>
|
||||
<div class="bg-light rounded d-flex align-items-center justify-content-center" style="width:40px; height:40px;">
|
||||
<i class="fas fa-image text-muted"></i>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><input type="number" step="0.01" class="input-cell cost-input" data-field="costo_producto" value="<?php echo $c['costo_producto']; ?>"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell cost-input" data-field="costo_fijo_film" value="<?php echo $c['costo_fijo_film']; ?>"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell cost-input" data-field="comision_asesora" value="<?php echo $c['comision_asesora']; ?>"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell cost-input bg-provincia" data-field="comision_asesora_provincia" value="<?php echo $c['comision_asesora_provincia']; ?>"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell cost-input" data-field="delivery" value="<?php echo $c['delivery']; ?>"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell cost-input bg-provincia" data-field="delivery_provincia" value="<?php echo $c['delivery_provincia']; ?>"></td>
|
||||
<td><input type="number" step="0.01" class="input-cell cost-input" data-field="costo_publicitario" value="<?php echo $c['costo_publicitario']; ?>"></td>
|
||||
|
||||
<td><input type="text" class="input-cell promo-input" data-field="promo_1" value="<?php echo htmlspecialchars($c['promo_1']); ?>"></td>
|
||||
<td>
|
||||
<div class="recaudo-v3 mb-1 <?php echo $r1_l >= 0 ? 'text-success' : 'text-danger'; ?>" id="r1l-<?php echo $c['id']; ?>">
|
||||
<span class="recaudo-label">LOCAL</span>
|
||||
<?php echo $r1_l !== null ? 'S/ '.number_format($r1_l, 2) : '-'; ?>
|
||||
</div>
|
||||
<div class="recaudo-v3 bg-provincia <?php echo $r1_p >= 0 ? 'text-success' : 'text-danger'; ?>" id="r1p-<?php echo $c['id']; ?>">
|
||||
<span class="recaudo-label">PROVINCIA</span>
|
||||
<?php echo $r1_p !== null ? 'S/ '.number_format($r1_p, 2) : '-'; ?>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td><input type="text" class="input-cell promo-input" data-field="promo_2" value="<?php echo htmlspecialchars($c['promo_2']); ?>"></td>
|
||||
<td>
|
||||
<div class="recaudo-v3 mb-1 <?php echo $r2_l >= 0 ? 'text-success' : 'text-danger'; ?>" id="r2l-<?php echo $c['id']; ?>">
|
||||
<span class="recaudo-label">LOCAL</span>
|
||||
<?php echo $r2_l !== null ? 'S/ '.number_format($r2_l, 2) : '-'; ?>
|
||||
</div>
|
||||
<div class="recaudo-v3 bg-provincia <?php echo $r2_p >= 0 ? 'text-success' : 'text-danger'; ?>" id="r2p-<?php echo $c['id']; ?>">
|
||||
<span class="recaudo-label">PROVINCIA</span>
|
||||
<?php echo $r2_p !== null ? 'S/ '.number_format($r2_p, 2) : '-'; ?>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td><input type="text" class="input-cell promo-input" data-field="promo_3" value="<?php echo htmlspecialchars($c['promo_3']); ?>"></td>
|
||||
<td>
|
||||
<div class="recaudo-v3 mb-1 <?php echo $r3_l >= 0 ? 'text-success' : 'text-danger'; ?>" id="r3l-<?php echo $c['id']; ?>">
|
||||
<span class="recaudo-label">LOCAL</span>
|
||||
<?php echo $r3_l !== null ? 'S/ '.number_format($r3_l, 2) : '-'; ?>
|
||||
</div>
|
||||
<div class="recaudo-v3 bg-provincia <?php echo $r3_p >= 0 ? 'text-success' : 'text-danger'; ?>" id="r3p-<?php echo $c['id']; ?>">
|
||||
<span class="recaudo-label">PROVINCIA</span>
|
||||
<?php echo $r3_p !== null ? 'S/ '.number_format($r3_p, 2) : '-'; ?>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="text-center">
|
||||
<button class="btn btn-danger btn-action" onclick="eliminarRow(<?php echo $c['id']; ?>)" title="Eliminar">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Nuevo -->
|
||||
<div class="modal fade" id="modalNuevoV3" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<form action="save_marketing_video_v3.php" method="POST" enctype="multipart/form-data">
|
||||
<input type="hidden" name="redirect" value="calculo_costos_v3.php?success=1">
|
||||
<div class="modal-header bg-primary text-white">
|
||||
<h5 class="modal-title"><i class="fas fa-plus-circle me-2"></i> Nuevo Producto (V3)</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body p-4">
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Seleccionar Producto</label>
|
||||
<select name="producto_id" class="form-select form-select-lg" required onchange="fetchProductCost(this.value)">
|
||||
<option value="">Seleccionar...</option>
|
||||
<?php foreach ($productos_select as $p): ?>
|
||||
<option value="<?php echo $p['id']; ?>"><?php echo htmlspecialchars($p['nombre']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-bold">Costo Base (S/)</label>
|
||||
<input type="number" name="costo_producto" id="costo_producto_nuevo_v3" class="form-control" step="0.01" placeholder="0.00">
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label fw-bold">Orden de Lista</label>
|
||||
<input type="number" name="orden" class="form-control" value="1">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-0">
|
||||
<label class="form-label fw-bold">Imagen del Producto</label>
|
||||
<input type="file" name="foto_producto" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-primary px-4">Crear Registro</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function fetchProductCost(productId) {
|
||||
if (!productId) return;
|
||||
fetch(`get_product_details.php?id=${productId}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success && data.product.costo) {
|
||||
document.getElementById('costo_producto_nuevo_v3').value = data.product.costo;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll('.input-cell').forEach(input => {
|
||||
// Actualización instantánea visual
|
||||
input.addEventListener('input', function() {
|
||||
const row = this.closest('tr');
|
||||
recalculateRowVisual(row);
|
||||
});
|
||||
|
||||
// Guardado real al salir del cuadro
|
||||
input.addEventListener('change', function() {
|
||||
const row = this.closest('tr');
|
||||
const id = row.dataset.id;
|
||||
const field = this.dataset.field;
|
||||
const value = this.value;
|
||||
|
||||
this.classList.add('saving');
|
||||
|
||||
fetch('update_marketing_costos_field_v3.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ id, field, value })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
this.classList.remove('saving');
|
||||
if (data.success) {
|
||||
this.classList.add('saved');
|
||||
setTimeout(() => this.classList.remove('saved'), 1000);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function recalculateRowVisual(row) {
|
||||
const id = row.dataset.id;
|
||||
const costProd = parseFloat(row.querySelector('[data-field="costo_producto"]').value) || 0;
|
||||
const costFilm = parseFloat(row.querySelector('[data-field="costo_fijo_film"]').value) || 0;
|
||||
const costAsesora = parseFloat(row.querySelector('[data-field="comision_asesora"]').value) || 0;
|
||||
const costAsesoraP = parseFloat(row.querySelector('[data-field="comision_asesora_provincia"]').value) || 0;
|
||||
const costDelivery = parseFloat(row.querySelector('[data-field="delivery"]').value) || 0;
|
||||
const costDeliveryP = parseFloat(row.querySelector('[data-field="delivery_provincia"]').value) || 0;
|
||||
const costPublicidad = parseFloat(row.querySelector('[data-field="costo_publicitario"]').value) || 0;
|
||||
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
const promoVal = row.querySelector(`[data-field="promo_${i}"]`).value;
|
||||
const match = promoVal.match(/[\d.]+/);
|
||||
const pVal = match ? parseFloat(match[0]) : 0;
|
||||
|
||||
const recaudoElL = row.querySelector(`#r${i}l-${id}`);
|
||||
const recaudoElP = row.querySelector(`#r${i}p-${id}`);
|
||||
|
||||
if (pVal > 0) {
|
||||
// Local
|
||||
const recaudoL = pVal - ((costProd + costFilm) * i + costAsesora + costDelivery + costPublicidad);
|
||||
recaudoElL.innerHTML = `<span class="recaudo-label">LOCAL</span>S/ ${recaudoL.toFixed(2)}`;
|
||||
recaudoElL.className = 'recaudo-v3 mb-1 ' + (recaudoL >= 0 ? 'text-success' : 'text-danger');
|
||||
|
||||
// Provincia
|
||||
const recaudoP = pVal - ((costProd + costFilm) * i + costAsesoraP + costDeliveryP + costPublicidad);
|
||||
recaudoElP.innerHTML = `<span class="recaudo-label">PROVINCIA</span>S/ ${recaudoP.toFixed(2)}`;
|
||||
recaudoElP.className = 'recaudo-v3 bg-provincia ' + (recaudoP >= 0 ? 'text-success' : 'text-danger');
|
||||
} else {
|
||||
recaudoElL.innerHTML = `<span class="recaudo-label">LOCAL</span>-`;
|
||||
recaudoElP.innerHTML = `<span class="recaudo-label">PROVINCIA</span>-`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function eliminarRow(id) {
|
||||
if (confirm('¿Eliminar este registro de la V3?')) {
|
||||
window.location.href = 'delete_marketing_video_v3.php?id=' + id;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php include 'layout_footer.php'; ?>
|
||||
@ -0,0 +1,4 @@
|
||||
-- Add provincia columns to marketing_costos_v3
|
||||
ALTER TABLE marketing_costos_v3
|
||||
ADD COLUMN comision_asesora_provincia DECIMAL(10,2) DEFAULT 0.00 AFTER comision_asesora,
|
||||
ADD COLUMN delivery_provincia DECIMAL(10,2) DEFAULT 0.00 AFTER delivery;
|
||||
33
delete_marketing_video_v3.php
Normal file
33
delete_marketing_video_v3.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
session_start();
|
||||
include 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id']) || !in_array($_SESSION['user_role'], ['Administrador', 'admin'])) {
|
||||
header('Location: login.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$db = db();
|
||||
|
||||
if (isset($_GET['id'])) {
|
||||
$id = $_GET['id'];
|
||||
|
||||
// Obtener la ruta de la foto para borrarla
|
||||
$stmt = $db->prepare("SELECT foto_producto FROM marketing_videos_v3 WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$video = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($video) {
|
||||
if (!empty($video['foto_producto']) && file_exists($video['foto_producto'])) {
|
||||
unlink($video['foto_producto']);
|
||||
}
|
||||
|
||||
// Borrar de ambas tablas V3
|
||||
$db->prepare("DELETE FROM marketing_costos_v3 WHERE video_id = ?")->execute([$id]);
|
||||
$db->prepare("DELETE FROM marketing_videos_v3 WHERE id = ?")->execute([$id]);
|
||||
}
|
||||
}
|
||||
|
||||
header("Location: calculo_costos_v3.php?success=deleted");
|
||||
exit;
|
||||
?>
|
||||
@ -256,10 +256,10 @@ $navItems = [
|
||||
'text' => 'Producción de Video',
|
||||
'roles' => ['Administrador', 'admin']
|
||||
],
|
||||
'calculo_costos' => [
|
||||
'url' => 'calculo_costos_v2.php',
|
||||
'calculo_costos_v3' => [
|
||||
'url' => 'calculo_costos_v3.php',
|
||||
'icon' => 'fa-calculator',
|
||||
'text' => 'Cálculo de Costos',
|
||||
'text' => 'Cálculo de Costos V3',
|
||||
'roles' => ['Administrador', 'admin']
|
||||
],
|
||||
'marketing_assets' => [
|
||||
|
||||
58
save_marketing_video_v3.php
Normal file
58
save_marketing_video_v3.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
include 'db/config.php';
|
||||
session_start();
|
||||
|
||||
if (!isset($_SESSION['user_id']) || !in_array($_SESSION['user_role'], ['Administrador', 'admin'])) {
|
||||
header('Location: login.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||||
$db = db();
|
||||
|
||||
$producto_id = !empty($_POST['producto_id']) ? $_POST['producto_id'] : null;
|
||||
$orden = !empty($_POST['orden']) ? $_POST['orden'] : 0;
|
||||
$costo_producto = !empty($_POST['costo_producto']) ? $_POST['costo_producto'] : 0;
|
||||
|
||||
$foto_path = null;
|
||||
|
||||
if (isset($_FILES['foto_producto']) && $_FILES['foto_producto']['error'] == 0) {
|
||||
$target_dir = "assets/uploads/marketing_images/";
|
||||
if (!is_dir($target_dir)) {
|
||||
mkdir($target_dir, 0777, true);
|
||||
}
|
||||
$file_extension = pathinfo($_FILES["foto_producto"]["name"], PATHINFO_EXTENSION);
|
||||
$file_name = uniqid() . '_v3.' . $file_extension;
|
||||
$target_file = $target_dir . $file_name;
|
||||
|
||||
if (move_uploaded_file($_FILES["foto_producto"]["tmp_name"], $target_file)) {
|
||||
$foto_path = $target_file;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $db->prepare("INSERT INTO marketing_videos_v3 (
|
||||
producto_id,
|
||||
foto_producto,
|
||||
estado,
|
||||
orden,
|
||||
fecha_creacion
|
||||
) VALUES (?, ?, 'PENDIENTE', ?, CURRENT_TIMESTAMP)");
|
||||
$stmt->execute([
|
||||
$producto_id,
|
||||
$foto_path,
|
||||
$orden
|
||||
]);
|
||||
$video_id = $db->lastInsertId();
|
||||
|
||||
// Guardar costo inicial en la tabla de costos V3
|
||||
$stmt_costo = $db->prepare("INSERT INTO marketing_costos_v3 (video_id, costo_producto, inversion_total) VALUES (?, ?, ?)");
|
||||
$stmt_costo->execute([$video_id, $costo_producto, $costo_producto]);
|
||||
|
||||
$redirect = $_POST['redirect'] ?? 'calculo_costos_v3.php?success=1';
|
||||
header('Location: ' . $redirect);
|
||||
} catch (PDOException $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
?>
|
||||
@ -37,7 +37,7 @@ try {
|
||||
$exists = $stmt->fetch();
|
||||
|
||||
if ($exists) {
|
||||
$sql = "UPDATE marketing_costos SET $field = ? WHERE video_id = ?";
|
||||
$sql = "UPDATE marketing_costos SET $field = ?, updated_at = CURRENT_TIMESTAMP WHERE video_id = ?";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$value, $video_id]);
|
||||
} else {
|
||||
@ -46,16 +46,18 @@ try {
|
||||
$stmt->execute([$video_id, $value]);
|
||||
}
|
||||
|
||||
// Recalculate inversion_total
|
||||
// Recalculate inversion_total - Fetching fresh data after update
|
||||
$stmt = $pdo->prepare("SELECT costo_producto, costo_fijo_film, comision_asesora, delivery, costo_publicitario FROM marketing_costos WHERE video_id = ?");
|
||||
$stmt->execute([$video_id]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$total = ($row['costo_producto'] ?? 0) +
|
||||
($row['costo_fijo_film'] ?? 0) +
|
||||
($row['comision_asesora'] ?? 0) +
|
||||
($row['delivery'] ?? 0) +
|
||||
($row['costo_publicitario'] ?? 0);
|
||||
$costo_prod = floatval($row['costo_producto'] ?? 0);
|
||||
$costo_film = floatval($row['costo_fijo_film'] ?? 0);
|
||||
$costo_asesora = floatval($row['comision_asesora'] ?? 0);
|
||||
$costo_delivery = floatval($row['delivery'] ?? 0);
|
||||
$costo_pub = floatval($row['costo_publicitario'] ?? 0);
|
||||
|
||||
$total = $costo_prod + $costo_film + $costo_asesora + $costo_delivery + $costo_pub;
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE marketing_costos SET inversion_total = ? WHERE video_id = ?");
|
||||
$stmt->execute([$total, $video_id]);
|
||||
|
||||
76
update_marketing_costos_field_v3.php
Normal file
76
update_marketing_costos_field_v3.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id']) || !in_array($_SESSION['user_role'], ['Administrador', 'admin'])) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Acceso no autorizado.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (!$data || !isset($data['id']) || !isset($data['field']) || !isset($data['value'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Datos incompletos.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$video_id = $data['id'];
|
||||
$field = $data['field'];
|
||||
$value = $data['value'];
|
||||
|
||||
// Campos permitidos
|
||||
$allowed_fields = [
|
||||
'costo_producto', 'costo_fijo_film', 'comision_asesora', 'delivery',
|
||||
'costo_publicitario', 'promo_1', 'promo_2', 'promo_3',
|
||||
'comision_asesora_provincia', 'delivery_provincia'
|
||||
];
|
||||
if (!in_array($field, $allowed_fields)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Campo no permitido.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// Verificar si existe el registro en costos V3
|
||||
$stmt = $pdo->prepare("SELECT id FROM marketing_costos_v3 WHERE video_id = ?");
|
||||
$stmt->execute([$video_id]);
|
||||
$exists = $stmt->fetch();
|
||||
|
||||
if ($exists) {
|
||||
$sql = "UPDATE marketing_costos_v3 SET $field = ?, updated_at = CURRENT_TIMESTAMP WHERE video_id = ?";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$value, $video_id]);
|
||||
} else {
|
||||
$sql = "INSERT INTO marketing_costos_v3 (video_id, $field) VALUES (?, ?)";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$video_id, $value]);
|
||||
}
|
||||
|
||||
// Recalcular inversion_total (Local)
|
||||
$stmt = $pdo->prepare("SELECT costo_producto, costo_fijo_film, comision_asesora, delivery, costo_publicitario FROM marketing_costos_v3 WHERE video_id = ?");
|
||||
$stmt->execute([$video_id]);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
$total = floatval($row['costo_producto'] ?? 0) +
|
||||
floatval($row['costo_fijo_film'] ?? 0) +
|
||||
floatval($row['comision_asesora'] ?? 0) +
|
||||
floatval($row['delivery'] ?? 0) +
|
||||
floatval($row['costo_publicitario'] ?? 0);
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE marketing_costos_v3 SET inversion_total = ? WHERE video_id = ?");
|
||||
$stmt->execute([$total, $video_id]);
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Actualizado en V3',
|
||||
'new_total' => $total
|
||||
]);
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Error: ' . $e->getMessage()]);
|
||||
}
|
||||
?>
|
||||
Loading…
x
Reference in New Issue
Block a user