Tul xxx Tul
User / IP
:
216.73.216.217
Host / Server
:
45.84.207.204 / aircan.me
System
:
Linux lt-bnk-web1726.main-hosting.eu 5.14.0-611.36.1.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Mar 3 11:23:52 EST 2026 x86_64
Command
|
Upload
|
Create
Mass Deface
|
Jumping
|
Symlink
|
Reverse Shell
Ping
|
Port Scan
|
DNS Lookup
|
Whois
|
Header
|
cURL
:
/
home
/
u931257429
/
domains
/
aircan.me
/
public_html
/
piscina
/
app
/
models
/
Viewing: Caja.php
<?php namespace App\Models; require_once dirname(__DIR__, 2) . '/config/database.php'; use mysqli; class Caja { private static array $metodosPago = [ 'Efectivo' => ['icono' => 'fa-solid fa-money-bill-wave', 'clase' => 'text-success'], 'Tarjeta' => ['icono' => 'fa-solid fa-credit-card', 'clase' => 'text-primary'], 'Transferencia/QR' => ['icono' => 'fa-solid fa-qrcode', 'clase' => 'text-warning'], ]; public static function movimientos(): array { $caja = self::cajaAbierta(); if (!$caja) { return []; } $conn = self::connection(); $stmt = $conn->prepare('SELECT id, caja_id, tipo, origen, cliente, metodo, descripcion, monto, fecha FROM movimientos_caja WHERE caja_id = ? ORDER BY fecha DESC'); $stmt->bind_param('i', $caja['id']); $stmt->execute(); $resultado = $stmt->get_result(); if (!$resultado) { return []; } $movimientos = []; while ($row = $resultado->fetch_assoc()) { $movimientos[] = self::mapMovimiento($row); } return $movimientos; } /** * Historial completo de movimientos (todos los registros), ordenados del más reciente al más antiguo. * @return array<int,array<string,mixed>> */ public static function movimientosHistorial(): array { $conn = self::connection(); $sql = 'SELECT id, caja_id, tipo, origen, cliente, metodo, descripcion, monto, fecha FROM movimientos_caja ORDER BY fecha DESC'; $resultado = $conn->query($sql); if (!$resultado) { return []; } $movimientos = []; while ($row = $resultado->fetch_assoc()) { $movimientos[] = self::mapMovimiento($row); } return $movimientos; } /** * Movimientos anteriores a hoy (excluye los de hoy) de TODO el historial. * @return array<int,array<string,mixed>> */ public static function movimientosAnteriores(): array { $conn = self::connection(); $sql = 'SELECT id, caja_id, tipo, origen, cliente, metodo, descripcion, monto, fecha FROM movimientos_caja WHERE DATE(fecha) < CURDATE() ORDER BY fecha DESC'; $resultado = $conn->query($sql); if (!$resultado) { return []; } $movimientos = []; while ($row = $resultado->fetch_assoc()) { $movimientos[] = self::mapMovimiento($row); } return $movimientos; } /** * Movimientos para el "Flujo de caja diario": * - Ingresos de hoy de orígenes: Entradas, Servicios, Restaurante * - Egresos de hoy (cualquier origen) * Siempre limitados a la caja abierta actual. * @return array<int,array<string,mixed>> */ public static function movimientosFlujoHoy(): array { $caja = self::cajaAbierta(); if (!$caja) { return []; } $conn = self::connection(); $sql = "SELECT id, caja_id, tipo, origen, cliente, metodo, descripcion, monto, fecha FROM movimientos_caja WHERE caja_id = ? AND DATE(fecha) = CURDATE() AND ( tipo = 'egreso' OR (tipo = 'ingreso' AND origen IN (?, ?, ?, ?, ?, ?, ?)) ) ORDER BY fecha DESC"; $stmt = $conn->prepare($sql); $o1 = 'Entradas'; $o2 = 'Entrada'; $o3 = 'Servicios'; $o4 = 'Servicio'; $o5 = 'Servicio por hora'; $o6 = 'Restaurante'; $o7 = 'Comida/Bebida'; $stmt->bind_param('isssssss', $caja['id'], $o1, $o2, $o3, $o4, $o5, $o6, $o7); $stmt->execute(); $resultado = $stmt->get_result(); if (!$resultado) { return []; } $movimientos = []; while ($row = $resultado->fetch_assoc()) { $movimientos[] = self::mapMovimiento($row); } return $movimientos; } public static function movimientosRecientes(int $limite = 10): array { $conn = self::connection(); $sql = 'SELECT id, caja_id, tipo, origen, cliente, metodo, descripcion, monto, fecha FROM movimientos_caja ORDER BY fecha DESC LIMIT ?'; $stmt = $conn->prepare($sql); $stmt->bind_param('i', $limite); $stmt->execute(); $resultado = $stmt->get_result(); if (!$resultado) { return []; } $movimientos = []; while ($row = $resultado->fetch_assoc()) { $movimientos[] = self::mapMovimiento($row); } return $movimientos; } public static function movimientosDelDia(?string $fecha = null): array { $caja = self::cajaAbierta(); if (!$caja) { return []; } $conn = self::connection(); $fecha = $fecha ?? date('Y-m-d'); $sql = 'SELECT id, caja_id, tipo, origen, cliente, metodo, descripcion, monto, fecha FROM movimientos_caja WHERE caja_id = ? AND DATE(fecha) = ? ORDER BY fecha DESC'; $stmt = $conn->prepare($sql); $stmt->bind_param('is', $caja['id'], $fecha); $stmt->execute(); $resultado = $stmt->get_result(); if (!$resultado) { return []; } $movimientos = []; while ($row = $resultado->fetch_assoc()) { $movimientos[] = self::mapMovimiento($row); } return $movimientos; } public static function resumenDiario(?string $fecha = null): array { $caja = self::cajaAbierta(); if (!$caja) { return [ 'ingresos' => 0.0, 'egresos' => 0.0, 'balance' => 0.0, 'movimientos' => 0, ]; } $conn = self::connection(); $fecha = $fecha ?? date('Y-m-d'); $sql = "SELECT SUM(CASE WHEN tipo = 'ingreso' THEN monto ELSE 0 END) AS ingresos, SUM(CASE WHEN tipo = 'egreso' THEN monto ELSE 0 END) AS egresos, COUNT(*) AS movimientos FROM movimientos_caja WHERE caja_id = ? AND DATE(fecha) = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param('is', $caja['id'], $fecha); $stmt->execute(); $resultado = $stmt->get_result()->fetch_assoc(); $ingresos = (float) ($resultado['ingresos'] ?? 0); $egresos = (float) ($resultado['egresos'] ?? 0); return [ 'ingresos' => $ingresos, 'egresos' => $egresos, 'balance' => $ingresos - $egresos, 'movimientos' => (int) ($resultado['movimientos'] ?? 0), ]; } public static function registrarCobro(array $data): array { return self::guardarMovimiento('ingreso', $data); } public static function registrarEgreso(array $data): array { $data['origen'] = $data['origen'] ?? 'Egreso'; return self::guardarMovimiento('egreso', $data); } public static function filtros(array $opciones = []): array { $conn = self::connection(); $conditions = []; $params = []; $types = ''; $desde = $opciones['desde'] ?? null; $hasta = $opciones['hasta'] ?? null; $tipo = strtolower((string) ($opciones['tipo'] ?? '')); if ($desde) { $conditions[] = 'DATE(fecha) >= ?'; $params[] = $desde; $types .= 's'; } if ($hasta) { $conditions[] = 'DATE(fecha) <= ?'; $params[] = $hasta; $types .= 's'; } if (in_array($tipo, ['ingreso', 'egreso'], true)) { $conditions[] = 'tipo = ?'; $params[] = $tipo; $types .= 's'; } $sql = 'SELECT id, caja_id, tipo, origen, cliente, metodo, descripcion, monto, fecha FROM movimientos_caja'; if (!empty($conditions)) { $sql .= ' WHERE ' . implode(' AND ', $conditions); } $sql .= ' ORDER BY fecha DESC'; if ($types !== '') { $stmt = $conn->prepare($sql); $stmt->bind_param($types, ...$params); $stmt->execute(); $resultado = $stmt->get_result(); } else { $resultado = $conn->query($sql); } if (!$resultado) { return []; } $movimientos = []; while ($row = $resultado->fetch_assoc()) { $movimientos[] = self::mapMovimiento($row); } return $movimientos; } public static function totales(array $movimientos): array { $ingresos = array_sum(array_map(fn ($movimiento) => $movimiento['tipo'] === 'Ingreso' ? $movimiento['monto'] : 0, $movimientos)); $egresos = array_sum(array_map(fn ($movimiento) => $movimiento['tipo'] === 'Egreso' ? $movimiento['monto'] : 0, $movimientos)); return [ 'ingresos' => $ingresos, 'egresos' => $egresos, 'balance' => $ingresos - $egresos, ]; } public static function resumenMetodos(array $movimientos): array { $metodos = []; foreach (self::metodos() as $metodo) { $metodos[$metodo] = 0; } foreach ($movimientos as $movimiento) { if ($movimiento['tipo'] !== 'Ingreso') { continue; } if (!isset($metodos[$movimiento['metodo']])) { $metodos[$movimiento['metodo']] = 0; } $metodos[$movimiento['metodo']] += $movimiento['monto']; } return $metodos; } public static function cierres(): array { $conn = self::connection(); $sql = 'SELECT id, fecha_apertura, fecha_cierre, total_ingresos, total_egresos, estado FROM caja ORDER BY fecha_apertura DESC'; $resultado = $conn->query($sql); if (!$resultado) { return []; } $cierres = []; while ($row = $resultado->fetch_assoc()) { $cierres[] = self::mapCaja($row); } return $cierres; } public static function registrarCierre(array $resumen): array { $conn = self::connection(); $caja = self::cajaAbierta(); if (!$caja) { throw new \RuntimeException('No hay una caja abierta para cerrar.'); } $conn->begin_transaction(); try { $totales = self::totalesPorCaja((int) $caja['id']); $ingresos = $totales['ingresos']; $egresos = $totales['egresos']; $stmt = $conn->prepare('UPDATE caja SET estado = "cerrada", fecha_cierre = NOW(), total_ingresos = ?, total_egresos = ? WHERE id = ?'); $stmt->bind_param('ddi', $ingresos, $egresos, $caja['id']); $stmt->execute(); $conn->commit(); } catch (\Throwable $e) { $conn->rollback(); throw $e; } $actualizada = self::findCaja((int) $caja['id']); if (!$actualizada) { throw new \RuntimeException('No fue posible recuperar la caja cerrada.'); } return [ 'id' => $actualizada['id'], 'fecha' => $actualizada['fecha_cierre'] ?? date('Y-m-d'), 'hora' => $actualizada['hora_cierre'] ?? date('H:i'), 'resumen' => [ 'ingresos' => $actualizada['total_ingresos'], 'egresos' => $actualizada['total_egresos'], 'balance' => $actualizada['total_ingresos'] - $actualizada['total_egresos'], ], ]; } public static function reiniciarCaja(): void { if (!self::cajaAbierta()) { self::abrirCaja(); } } public static function metodos(): array { return array_keys(self::$metodosPago); } public static function metodoInfo(string $metodo): array { return self::$metodosPago[$metodo] ?? ['icono' => 'fa-solid fa-circle-info', 'clase' => 'text-muted']; } public static function metodosInfo(): array { return self::$metodosPago; } public static function ultimoCierre(): ?array { $conn = self::connection(); $sql = 'SELECT id, fecha_apertura, fecha_cierre, total_ingresos, total_egresos, estado FROM caja WHERE estado = "cerrada" ORDER BY fecha_cierre DESC LIMIT 1'; $resultado = $conn->query($sql); if (!$resultado) { return null; } $row = $resultado->fetch_assoc(); if (!$row) { return null; } $cierre = self::mapCaja($row); return [ 'id' => $cierre['id'], 'fecha' => $cierre['fecha_cierre'], 'hora' => $cierre['hora_cierre'], 'resumen' => [ 'ingresos' => $cierre['total_ingresos'], 'egresos' => $cierre['total_egresos'], 'balance' => $cierre['total_ingresos'] - $cierre['total_egresos'], ], ]; } private static function mapMovimiento(array $row): array { $fecha = $row['fecha'] ? new \DateTimeImmutable($row['fecha']) : new \DateTimeImmutable(); return [ 'id' => (int) $row['id'], 'caja_id' => (int) $row['caja_id'], 'tipo' => ucfirst($row['tipo']), 'origen' => $row['origen'] ?? 'Otros', 'cliente' => $row['cliente'] ?? null, 'concepto' => $row['descripcion'] ?? '', 'monto' => (float) $row['monto'], 'metodo' => $row['metodo'] ?? 'Efectivo', 'fecha' => $fecha->format('Y-m-d'), 'hora' => $fecha->format('h:i A'), ]; } private static function mapCaja(array $row): array { $apertura = $row['fecha_apertura'] ? new \DateTimeImmutable($row['fecha_apertura']) : null; $cierre = $row['fecha_cierre'] ? new \DateTimeImmutable($row['fecha_cierre']) : null; return [ 'id' => (int) $row['id'], 'fecha_apertura' => $apertura?->format('Y-m-d'), 'hora_apertura' => $apertura?->format('H:i'), 'fecha_cierre' => $cierre?->format('Y-m-d'), 'hora_cierre' => $cierre?->format('H:i'), 'total_ingresos' => (float) $row['total_ingresos'], 'total_egresos' => (float) $row['total_egresos'], 'estado' => $row['estado'], ]; } private static function guardarMovimiento(string $tipo, array $data): array { $tipo = strtolower($tipo) === 'egreso' ? 'egreso' : 'ingreso'; $conn = self::connection(); $caja = self::ensureCajaAbierta(); $metodo = $data['metodo'] ?? 'Efectivo'; if (!in_array($metodo, self::metodos(), true)) { $metodo = 'Efectivo'; } $fechaMovimiento = self::fechaMovimiento($data); $stmt = $conn->prepare('INSERT INTO movimientos_caja (caja_id, tipo, origen, cliente, metodo, descripcion, monto, fecha) VALUES (?, ?, ?, ?, ?, ?, ?, ?)'); $origen = $data['origen'] ?? ($tipo === 'ingreso' ? 'Otros' : 'Egreso'); $cliente = $data['cliente'] ?? null; $concepto = $data['concepto'] ?? ''; $monto = isset($data['monto']) ? (float) $data['monto'] : 0.0; $stmt->bind_param('isssssds', $caja['id'], $tipo, $origen, $cliente, $metodo, $concepto, $monto, $fechaMovimiento); $stmt->execute(); $movimientoId = $stmt->insert_id; $updateSql = $tipo === 'ingreso' ? 'UPDATE caja SET total_ingresos = total_ingresos + ? WHERE id = ?' : 'UPDATE caja SET total_egresos = total_egresos + ? WHERE id = ?'; $update = $conn->prepare($updateSql); $update->bind_param('di', $monto, $caja['id']); $update->execute(); $movimiento = self::findMovimiento($movimientoId); if (!$movimiento) { throw new \RuntimeException('No fue posible registrar el movimiento de caja.'); } return $movimiento; } private static function findMovimiento(int $id): ?array { $conn = self::connection(); $stmt = $conn->prepare('SELECT id, caja_id, tipo, origen, cliente, metodo, descripcion, monto, fecha FROM movimientos_caja WHERE id = ? LIMIT 1'); $stmt->bind_param('i', $id); $stmt->execute(); $resultado = $stmt->get_result()->fetch_assoc(); return $resultado ? self::mapMovimiento($resultado) : null; } public static function eliminarMovimiento(int $id): bool { $conn = self::connection(); $conn->begin_transaction(); try { $stmt = $conn->prepare('SELECT id, caja_id, tipo, monto FROM movimientos_caja WHERE id = ? FOR UPDATE'); $stmt->bind_param('i', $id); $stmt->execute(); $row = $stmt->get_result()->fetch_assoc(); if (!$row) { $conn->rollback(); return false; } $cajaId = (int) $row['caja_id']; $tipo = strtolower((string) $row['tipo']); $monto = (float) $row['monto']; if ($tipo === 'ingreso') { $upd = $conn->prepare('UPDATE caja SET total_ingresos = GREATEST(0, total_ingresos - ?) WHERE id = ?'); } else { $upd = $conn->prepare('UPDATE caja SET total_egresos = GREATEST(0, total_egresos - ?) WHERE id = ?'); } $upd->bind_param('di', $monto, $cajaId); $upd->execute(); $del = $conn->prepare('DELETE FROM movimientos_caja WHERE id = ?'); $del->bind_param('i', $id); $del->execute(); $conn->commit(); return $del->affected_rows > 0; } catch (\Throwable $e) { $conn->rollback(); return false; } } private static function ensureCajaAbierta(): array { $caja = self::cajaAbierta(); $hoy = date('Y-m-d'); if ($caja) { $fechaApertura = $caja['fecha_apertura'] ?? $hoy; if ($fechaApertura !== $hoy) { self::cerrarCaja((int) $caja['id'], $fechaApertura . ' 23:59:59'); return self::abrirCaja(); } return $caja; } return self::abrirCaja(); } private static function cajaAbierta(): ?array { $conn = self::connection(); $sql = 'SELECT id, fecha_apertura, fecha_cierre, total_ingresos, total_egresos, estado FROM caja WHERE estado = "abierta" ORDER BY fecha_apertura DESC LIMIT 1'; $resultado = $conn->query($sql); if (!$resultado) { return null; } $row = $resultado->fetch_assoc(); return $row ? self::mapCaja($row) : null; } private static function abrirCaja(): array { $conn = self::connection(); $stmt = $conn->prepare('INSERT INTO caja (fecha_apertura, total_ingresos, total_egresos, estado) VALUES (?, 0, 0, "abierta")'); $ahora = date('Y-m-d H:i:s'); $stmt->bind_param('s', $ahora); $stmt->execute(); $caja = self::findCaja((int) $stmt->insert_id); if (!$caja) { throw new \RuntimeException('No fue posible abrir una nueva caja.'); } return $caja; } private static function findCaja(int $id): ?array { $conn = self::connection(); $stmt = $conn->prepare('SELECT id, fecha_apertura, fecha_cierre, total_ingresos, total_egresos, estado FROM caja WHERE id = ? LIMIT 1'); $stmt->bind_param('i', $id); $stmt->execute(); $resultado = $stmt->get_result()->fetch_assoc(); return $resultado ? self::mapCaja($resultado) : null; } private static function totalesPorCaja(int $cajaId): array { $conn = self::connection(); $stmt = $conn->prepare("SELECT SUM(CASE WHEN tipo = 'ingreso' THEN monto ELSE 0 END) AS ingresos, SUM(CASE WHEN tipo = 'egreso' THEN monto ELSE 0 END) AS egresos FROM movimientos_caja WHERE caja_id = ?"); $stmt->bind_param('i', $cajaId); $stmt->execute(); $resultado = $stmt->get_result()->fetch_assoc(); return [ 'ingresos' => (float) ($resultado['ingresos'] ?? 0), 'egresos' => (float) ($resultado['egresos'] ?? 0), ]; } private static function cerrarCaja(int $cajaId, ?string $fechaCierre = null): void { $conn = self::connection(); $totales = self::totalesPorCaja($cajaId); $fechaCierre = $fechaCierre ?: date('Y-m-d H:i:s'); $dt = new \DateTimeImmutable($fechaCierre); $fc = $dt->format('Y-m-d H:i:s'); $stmt = $conn->prepare('UPDATE caja SET fecha_cierre = ?, total_ingresos = ?, total_egresos = ?, estado = "cerrada" WHERE id = ?'); $ing = (float) ($totales['ingresos'] ?? 0); $egr = (float) ($totales['egresos'] ?? 0); $stmt->bind_param('sddi', $fc, $ing, $egr, $cajaId); $stmt->execute(); } public static function asegurarCajaDeHoy(): array { return self::ensureCajaAbierta(); } private static function fechaMovimiento(array $data): string { $fecha = $data['fecha'] ?? date('Y-m-d'); $hora = $data['hora'] ?? date('H:i:s'); $timestamp = sprintf('%s %s', $fecha, $hora); $dateTime = new \DateTimeImmutable($timestamp); return $dateTime->format('Y-m-d H:i:s'); } private static function connection(): mysqli { static $conn = null; if ($conn instanceof mysqli) { return $conn; } $db = new \Database(); $conn = $db->getConnection(); $conn->query("SET time_zone = '-06:00'"); return $conn; } }
Coded With 💗 by
0x6ick