Autosave: 20260220-170918
This commit is contained in:
parent
8914f6e2df
commit
b9b815f6ba
BIN
assets/uploads/vouchers/69988c4617737-Screenshot_29.png
Normal file
BIN
assets/uploads/vouchers/69988c4617737-Screenshot_29.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 240 KiB |
BIN
assets/uploads/vouchers/69988ed8545e6-228.png
Normal file
BIN
assets/uploads/vouchers/69988ed8545e6-228.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 453 KiB |
@ -0,0 +1,8 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS liquidaciones_provincia (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
fecha DATE NOT NULL,
|
||||||
|
provincia VARCHAR(255) NOT NULL,
|
||||||
|
monto DECIMAL(10, 2) DEFAULT 0.00,
|
||||||
|
estado VARCHAR(255) DEFAULT '',
|
||||||
|
UNIQUE KEY fecha_provincia (fecha, provincia)
|
||||||
|
);
|
||||||
@ -150,6 +150,12 @@ $navItems = [
|
|||||||
'icon' => 'fa-box',
|
'icon' => 'fa-box',
|
||||||
'text' => 'Productos',
|
'text' => 'Productos',
|
||||||
'roles' => ['Administrador', 'admin', 'Control Logistico']
|
'roles' => ['Administrador', 'admin', 'Control Logistico']
|
||||||
|
],
|
||||||
|
'liquidaciones_provincia' => [
|
||||||
|
'url' => 'liquidaciones_provincia.php',
|
||||||
|
'icon' => 'fa-file-invoice-dollar',
|
||||||
|
'text' => 'Liquidaciones Provincia',
|
||||||
|
'roles' => ['Administrador', 'admin', 'Control Logistico']
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
|||||||
210
liquidaciones_provincia.php
Normal file
210
liquidaciones_provincia.php
Normal file
@ -0,0 +1,210 @@
|
|||||||
|
<?php
|
||||||
|
require_once 'layout_header.php';
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
$month = isset($_GET['month']) ? $_GET['month'] : date('m');
|
||||||
|
$year = isset($_GET['year']) ? $_GET['year'] : date('Y');
|
||||||
|
|
||||||
|
$days_in_month = cal_days_in_month(CAL_GREGORIAN, $month, $year);
|
||||||
|
|
||||||
|
$provincias = ['LIMA', 'AREQUIPA', 'TRUJILLO', 'ICA', 'CUSCO', 'CAJAMARCA', 'CHICLAYO', 'PIURA'];
|
||||||
|
|
||||||
|
// Fetch data for the month
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare("SELECT fecha, provincia, monto, estado FROM liquidaciones_provincia WHERE MONTH(fecha) = ? AND YEAR(fecha) = ?");
|
||||||
|
$stmt->execute([$month, $year]);
|
||||||
|
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
// Organize data for easy access
|
||||||
|
$liquidaciones = [];
|
||||||
|
foreach ($data as $row) {
|
||||||
|
$liquidaciones[$row['fecha']][$row['provincia']] = [
|
||||||
|
'monto' => $row['monto'],
|
||||||
|
'estado' => $row['estado']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.table thead th {
|
||||||
|
background-color: #337ab7;
|
||||||
|
color: #ffffff;
|
||||||
|
font-weight: 600;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
.table tfoot th {
|
||||||
|
position: sticky;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #e9ecef;
|
||||||
|
z-index: 10;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
.table td[contenteditable="true"]:focus {
|
||||||
|
background-color: #fff3cd;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="container-fluid mt-4">
|
||||||
|
<h2>Liquidaciones Provincia</h2>
|
||||||
|
<p>Tabla de liquidaciones por provincia para el mes seleccionado.</p>
|
||||||
|
|
||||||
|
<form method="GET" action="liquidaciones_provincia.php" class="form-inline mb-4">
|
||||||
|
<div class="form-group mr-2">
|
||||||
|
<label for="month" class="mr-2">Mes:</label>
|
||||||
|
<select name="month" id="month" class="form-control">
|
||||||
|
<?php for ($m = 1; $m <= 12; $m++): ?>
|
||||||
|
<option value="<?php echo str_pad($m, 2, '0', STR_PAD_LEFT); ?>" <?php echo $m == $month ? 'selected' : ''; ?>>
|
||||||
|
<?php echo DateTime::createFromFormat('!m', $m)->format('F'); ?>
|
||||||
|
</option>
|
||||||
|
<?php endfor; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group mr-2">
|
||||||
|
<label for="year" class="mr-2">Año:</label>
|
||||||
|
<select name="year" id="year" class="form-control">
|
||||||
|
<?php for ($y = date('Y'); $y >= date('Y') - 5; $y--): ?>
|
||||||
|
<option value="<?php echo $y; ?>" <?php echo $y == $year ? 'selected' : ''; ?>><?php echo $y; ?></option>
|
||||||
|
<?php endfor; ?>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Filtrar</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="table-responsive" style="max-height: 70vh; overflow-y: auto;">
|
||||||
|
<table class="table table-bordered table-striped table-hover" style="width: 100%;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Fecha</th>
|
||||||
|
<?php foreach ($provincias as $provincia): ?>
|
||||||
|
<th><?php echo htmlspecialchars($provincia); ?></th>
|
||||||
|
<th>ESTADO</th>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php for ($day = 1; $day <= $days_in_month; $day++): ?>
|
||||||
|
<?php $date = date('Y-m-d', strtotime("$year-$month-$day")); ?>
|
||||||
|
<tr data-date="<?php echo $date; ?>">
|
||||||
|
<td><?php echo $date; ?></td>
|
||||||
|
<?php foreach ($provincias as $provincia): ?>
|
||||||
|
<?php
|
||||||
|
$monto = isset($liquidaciones[$date][$provincia]['monto']) ? number_format($liquidaciones[$date][$provincia]['monto'], 2, '.', '') : '0.00';
|
||||||
|
$estado = isset($liquidaciones[$date][$provincia]['estado']) ? htmlspecialchars($liquidaciones[$date][$provincia]['estado']) : '';
|
||||||
|
?>
|
||||||
|
<td class="editable-cell" contenteditable="true" data-provincia="<?php echo htmlspecialchars($provincia); ?>" data-column="monto"><?php echo $monto; ?></td>
|
||||||
|
<td class="editable-cell" contenteditable="true" data-provincia="<?php echo htmlspecialchars($provincia); ?>" data-column="estado"><?php echo $estado; ?></td>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tr>
|
||||||
|
<?php endfor; ?>
|
||||||
|
</tbody>
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<th>TOTAL</th>
|
||||||
|
<?php foreach ($provincias as $provincia): ?>
|
||||||
|
<th data-total-column="<?php echo htmlspecialchars($provincia); ?>">0.00</th>
|
||||||
|
<th></th>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const table = document.querySelector('.table');
|
||||||
|
|
||||||
|
function calculateTotals() {
|
||||||
|
const totals = {};
|
||||||
|
<?php foreach ($provincias as $provincia): ?>
|
||||||
|
totals['<?php echo $provincia; ?>'] = 0;
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
table.querySelectorAll('tbody tr').forEach(row => {
|
||||||
|
<?php foreach ($provincias as $provincia): ?>
|
||||||
|
const cell = row.querySelector(`td[data-provincia="<?php echo $provincia; ?>"][data-column="monto"]`);
|
||||||
|
if (cell) {
|
||||||
|
const value = parseFloat(cell.textContent.replace(/,/g, '')) || 0;
|
||||||
|
totals['<?php echo $provincia; ?>'] += value;
|
||||||
|
}
|
||||||
|
<?php endforeach; ?>
|
||||||
|
});
|
||||||
|
|
||||||
|
<?php foreach ($provincias as $provincia): ?>
|
||||||
|
const totalCell = table.querySelector(`tfoot th[data-total-column="<?php echo $provincia; ?>"]`);
|
||||||
|
if (totalCell) {
|
||||||
|
totalCell.textContent = totals['<?php echo $provincia; ?>'].toFixed(2);
|
||||||
|
}
|
||||||
|
<?php endforeach; ?>
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initial calculation
|
||||||
|
calculateTotals();
|
||||||
|
|
||||||
|
table.addEventListener('keydown', function(e) {
|
||||||
|
if (e.key === 'Enter' && e.target.classList.contains('editable-cell')) {
|
||||||
|
e.preventDefault();
|
||||||
|
e.target.blur(); // Trigger blur to save
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
table.addEventListener('blur', function(e) {
|
||||||
|
if (e.target.classList.contains('editable-cell')) {
|
||||||
|
const cell = e.target;
|
||||||
|
const row = cell.closest('tr');
|
||||||
|
const fecha = row.dataset.date;
|
||||||
|
const provincia = cell.dataset.provincia;
|
||||||
|
const columna = cell.dataset.column;
|
||||||
|
let valor = cell.textContent.trim();
|
||||||
|
|
||||||
|
if (columna === 'monto') {
|
||||||
|
let numValue = parseFloat(valor.replace(/,/g, ''));
|
||||||
|
if (isNaN(numValue)) {
|
||||||
|
numValue = 0;
|
||||||
|
}
|
||||||
|
valor = numValue;
|
||||||
|
// Format back to 2 decimal places for display
|
||||||
|
cell.textContent = numValue.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = { fecha, provincia, columna, valor };
|
||||||
|
|
||||||
|
fetch('save_liquidaciones_provincia.php', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(data)
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(result => {
|
||||||
|
if (result.success) {
|
||||||
|
if (columna === 'monto') {
|
||||||
|
calculateTotals();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('Failed to save:', result.message);
|
||||||
|
// alert('Error al guardar el dato.'); // Optional: notify user
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error:', error));
|
||||||
|
}
|
||||||
|
}, true); // Use capturing to ensure blur event is handled reliably
|
||||||
|
|
||||||
|
table.addEventListener('focus', function(e) {
|
||||||
|
if (e.target.classList.contains('editable-cell')) {
|
||||||
|
// Select all text in cell on focus
|
||||||
|
const selection = window.getSelection();
|
||||||
|
const range = document.createRange();
|
||||||
|
range.selectNodeContents(e.target);
|
||||||
|
selection.removeAllRanges();
|
||||||
|
selection.addRange(range);
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
require_once 'layout_footer.php';
|
||||||
|
?>
|
||||||
@ -46,7 +46,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
|
|
||||||
// 3. Registrar el movimiento
|
// 3. Registrar el movimiento
|
||||||
$sql_movement = "INSERT INTO stock_movements (product_id, sede_id, type, quantity, movement_date)
|
$sql_movement = "INSERT INTO stock_movements (product_id, sede_id, type, quantity, movement_date)
|
||||||
VALUES (:product_id, :sede_id, 'salida_manual', :quantity, NOW())";
|
VALUES (:product_id, :sede_id, 'salida', :quantity, NOW())";
|
||||||
$stmt_movement = $pdo->prepare($sql_movement);
|
$stmt_movement = $pdo->prepare($sql_movement);
|
||||||
$stmt_movement->bindParam(':product_id', $product_id, PDO::PARAM_INT);
|
$stmt_movement->bindParam(':product_id', $product_id, PDO::PARAM_INT);
|
||||||
$stmt_movement->bindParam(':sede_id', $sede_id, PDO::PARAM_INT);
|
$stmt_movement->bindParam(':sede_id', $sede_id, PDO::PARAM_INT);
|
||||||
|
|||||||
34
save_liquidaciones_provincia.php
Normal file
34
save_liquidaciones_provincia.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
require_once 'db/config.php';
|
||||||
|
|
||||||
|
$data = json_decode(file_get_contents('php://input'), true);
|
||||||
|
|
||||||
|
if ($data) {
|
||||||
|
$fecha = $data['fecha'];
|
||||||
|
$provincia = $data['provincia'];
|
||||||
|
$columna = $data['columna'];
|
||||||
|
$valor = $data['valor'];
|
||||||
|
|
||||||
|
// Column name validation
|
||||||
|
if ($columna === 'monto' || $columna === 'estado') {
|
||||||
|
try {
|
||||||
|
$pdo = db();
|
||||||
|
$sql = "INSERT INTO liquidaciones_provincia (fecha, provincia, $columna) VALUES (:fecha, :provincia, :valor)
|
||||||
|
ON DUPLICATE KEY UPDATE $columna = :valor";
|
||||||
|
$stmt = $pdo->prepare($sql);
|
||||||
|
$stmt->execute(['fecha' => $fecha, 'provincia' => $provincia, 'valor' => $valor]);
|
||||||
|
|
||||||
|
echo json_encode(['success' => true]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
http_response_code(500);
|
||||||
|
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['success' => false, 'message' => 'Invalid column name.']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
http_response_code(400);
|
||||||
|
echo json_encode(['success' => false, 'message' => 'No data received.']);
|
||||||
|
}
|
||||||
|
?>
|
||||||
Loading…
x
Reference in New Issue
Block a user