From 2caed5f3df85a36253e82d785f9c6d780afda328 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Tue, 3 Feb 2026 05:29:28 +0000 Subject: [PATCH] Autosave: 20260203-052927 --- db/migrations/048_create_flujo_caja_table.sql | 18 +++ flujo_de_caja.php | 151 ++++++++++++++++++ layout_header.php | 6 + recaudo_esperado.php | 86 +++++++--- save_flujo_caja.php | 40 +++++ 5 files changed, 279 insertions(+), 22 deletions(-) create mode 100644 db/migrations/048_create_flujo_caja_table.sql create mode 100644 flujo_de_caja.php create mode 100644 save_flujo_caja.php diff --git a/db/migrations/048_create_flujo_caja_table.sql b/db/migrations/048_create_flujo_caja_table.sql new file mode 100644 index 0000000..d15ea6b --- /dev/null +++ b/db/migrations/048_create_flujo_caja_table.sql @@ -0,0 +1,18 @@ +CREATE TABLE IF NOT EXISTS `flujo_caja` ( + `fecha` date NOT NULL, + `bcp_yape` decimal(10,2) DEFAULT '0.00', + `b_nacion` decimal(10,2) DEFAULT '0.00', + `interbank` decimal(10,2) DEFAULT '0.00', + `bbva` decimal(10,2) DEFAULT '0.00', + `otros_ingresos` decimal(10,2) DEFAULT '0.00', + `tu1` decimal(10,2) DEFAULT '0.00', + `tu2` decimal(10,2) DEFAULT '0.00', + `tu3` decimal(10,2) DEFAULT '0.00', + `fl1` decimal(10,2) DEFAULT '0.00', + `fl2` decimal(10,2) DEFAULT '0.00', + `fl3` decimal(10,2) DEFAULT '0.00', + `rc_envio` decimal(10,2) DEFAULT '0.00', + `rc_contraent` decimal(10,2) DEFAULT '0.00', + `total_inversion_publicitaria` decimal(10,2) DEFAULT '0.00', + PRIMARY KEY (`fecha`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/flujo_de_caja.php b/flujo_de_caja.php new file mode 100644 index 0000000..981f38d --- /dev/null +++ b/flujo_de_caja.php @@ -0,0 +1,151 @@ +prepare("SELECT * FROM flujo_caja WHERE fecha BETWEEN ? AND ?"); + $stmt->execute([$start_date, $end_date]); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($rows as $row) { + $flujo_data[$row['fecha']] = $row; + } +} catch (PDOException $e) { + // Handle error +} + +$columns = [ + 'bcp_yape', 'b_nacion', 'interbank', 'bbva', 'otros_ingresos', + 'tu1', 'tu2', 'tu3', 'fl1', 'fl2', 'fl3', + 'rc_envio', 'rc_contraent', 'total_inversion_publicitaria' +]; + +?> + +
+

Flujo de Caja

+

Registro y control de los movimientos de ingresos y gastos.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FechaIngresosInversion PublicitariaRC ENVIORC CONTRAENTTotal IngresosTotal Inversion PublicitariaRecaudo final
BCP/YAPEB. NACIONINTERBANKBBVAOtros IngresosTU 1TU 2TU 3FL1FL2FL3
0.000.000.00
+
+
+ + + + \ No newline at end of file diff --git a/layout_header.php b/layout_header.php index e461b2e..1d19cd5 100644 --- a/layout_header.php +++ b/layout_header.php @@ -103,6 +103,12 @@ $navItems = [ 'text' => 'Rentabilidad de Producto', 'roles' => ['Administrador', 'admin'] ], + 'flujo_de_caja' => [ + 'url' => 'flujo_de_caja.php', + 'icon' => 'fa-wallet', + 'text' => 'Flujo de Caja', + 'roles' => ['Administrador', 'admin'] + ], ] ], 'info_producto' => [ diff --git a/recaudo_esperado.php b/recaudo_esperado.php index e53665f..26c46d3 100644 --- a/recaudo_esperado.php +++ b/recaudo_esperado.php @@ -30,7 +30,48 @@ function normalize_for_grouping($string) { return trim($string); } +// Nueva función para parsear los productos usando la lista oficial +function parse_product_string($pedido_producto, $official_product_names) { + $found_products = []; + $remaining_string = $pedido_producto; + + while (strlen($remaining_string) > 0) { + $match_found = false; + foreach ($official_product_names as $official_name) { + if (stripos($remaining_string, $official_name) === 0) { + $found_products[] = $official_name; + $remaining_string = trim(substr($remaining_string, strlen($official_name))); + // Remove leading comma and spaces + if (isset($remaining_string[0]) && $remaining_string[0] == ',') { + $remaining_string = trim(substr($remaining_string, 1)); + } + $match_found = true; + break; + } + } + // If no official product is matched, we fallback to comma separation for robustness + if (!$match_found) { + $parts = explode(',', $remaining_string, 2); + $first_part = trim($parts[0]); + if (!empty($first_part)) { + $found_products[] = $first_part; + } + $remaining_string = isset($parts[1]) ? trim($parts[1]) : ''; + } + } + return $found_products; +} + + if (!empty($fecha_inicio_str) && !empty($fecha_fin_str)) { + // --- Obtener nombres oficiales de productos --- + $stmt_products = $pdo->query("SELECT nombre FROM products"); + $official_product_names = $stmt_products->fetchAll(PDO::FETCH_COLUMN); + // Sort by length descending to match longer names first + usort($official_product_names, function($a, $b) { + return strlen($b) - strlen($a); + }); + // --- Recaudo por Asesora --- $stmt_asesoras = $pdo->prepare(" SELECT @@ -64,33 +105,30 @@ if (!empty($fecha_inicio_str) && !empty($fecha_fin_str)) { if ($pedidos) { foreach ($pedidos as $pedido) { - $product_names = array_map('trim', explode(',', $pedido['producto'])); - $quantities = array_map('trim', explode('+', $pedido['cantidad'])); + // Usar la nueva función de parseo + $productos_nombres = parse_product_string($pedido['producto'], $official_product_names); + $cantidades = array_map('trim', explode('+', $pedido['cantidad'])); $monto_total_pedido = (float)$pedido['monto_total']; $asesor = $pedido['nombre_asesor'] ?? 'Sin Asesor'; - foreach ($product_names as $index => $producto_nombre) { - if (empty($producto_nombre)) continue; + foreach ($productos_nombres as $index => $nombre_producto) { + if (empty($nombre_producto)) continue; - $cantidad = isset($quantities[$index]) ? (int)$quantities[$index] : 1; - if ($cantidad == 0) $cantidad = 1; // Evitar división por cero y asegurar al menos una unidad + $cantidad_producto = isset($cantidades[$index]) ? (int)$cantidades[$index] : 1; + $monto_producto = ($index == 0) ? $monto_total_pedido : 0; - // El primer producto obtiene el monto total, los demás obtienen 0 - $monto_asignado = ($index === 0) ? $monto_total_pedido : 0; - - // Clave normalizada para agrupación - $normalized_key = normalize_for_grouping($producto_nombre); + $normalized_key = normalize_for_grouping($nombre_producto); // Acumular para "Resumen General de Productos Vendidos" if (!isset($productos_vendidos[$normalized_key])) { $productos_vendidos[$normalized_key] = [ - 'nombre_display' => $producto_nombre, + 'nombre_display' => $nombre_producto, 'unidades' => 0, - 'total_ingresos' => 0, + 'total_ingresos' => 0 ]; } - $productos_vendidos[$normalized_key]['unidades'] += $cantidad; - $productos_vendidos[$normalized_key]['total_ingresos'] += $monto_asignado; + $productos_vendidos[$normalized_key]['unidades'] += $cantidad_producto; + $productos_vendidos[$normalized_key]['total_ingresos'] += $monto_producto; // Acumular para "Desglose de Ventas por Asesor" if (!isset($ventas_por_asesor[$asesor])) { @@ -98,13 +136,13 @@ if (!empty($fecha_inicio_str) && !empty($fecha_fin_str)) { } if (!isset($ventas_por_asesor[$asesor][$normalized_key])) { $ventas_por_asesor[$asesor][$normalized_key] = [ - 'nombre_display' => $producto_nombre, + 'nombre_display' => $nombre_producto, 'unidades' => 0, - 'total_ingresos' => 0, + 'total_ingresos' => 0 ]; } - $ventas_por_asesor[$asesor][$normalized_key]['unidades'] += $cantidad; - $ventas_por_asesor[$asesor][$normalized_key]['total_ingresos'] += $monto_asignado; + $ventas_por_asesor[$asesor][$normalized_key]['unidades'] += $cantidad_producto; + $ventas_por_asesor[$asesor][$normalized_key]['total_ingresos'] += $monto_producto; } } } @@ -185,7 +223,9 @@ if (!empty($fecha_inicio_str) && !empty($fecha_fin_str)) { $a['unidades']; }); ?> - 0) ? $producto['total_ingresos'] / $producto['unidades'] : 0; ?> + 0) ? $producto['total_ingresos'] / $producto['unidades'] : 0; + ?> @@ -222,7 +262,9 @@ if (!empty($fecha_inicio_str) && !empty($fecha_fin_str)) { $a['unidades']; }); ?> - 0) ? $data['total_ingresos'] / $data['unidades'] : 0; ?> + 0) ? $data['total_ingresos'] / $data['unidades'] : 0; + ?> @@ -239,4 +281,4 @@ if (!empty($fecha_inicio_str) && !empty($fecha_fin_str)) { - \ No newline at end of file + diff --git a/save_flujo_caja.php b/save_flujo_caja.php new file mode 100644 index 0000000..7eb8768 --- /dev/null +++ b/save_flujo_caja.php @@ -0,0 +1,40 @@ +prepare($sql); + $stmt->execute(['fecha' => $fecha, '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.']); +} +?> \ No newline at end of file