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.
+
+
+
+
+
+ | Fecha |
+ Ingresos |
+ Inversion Publicitaria |
+ RC ENVIO |
+ RC CONTRAENT |
+ Total Ingresos |
+ Total Inversion Publicitaria |
+ Recaudo final |
+
+
+ | BCP/YAPE |
+ B. NACION |
+ INTERBANK |
+ BBVA |
+ Otros Ingresos |
+ TU 1 |
+ TU 2 |
+ TU 3 |
+ FL1 |
+ FL2 |
+ FL3 |
+
+
+
+
+
+ |
+
+ |
+
+ 0.00 |
+ 0.00 |
+ 0.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;
+ ?>
| = htmlspecialchars($producto['nombre_display']) ?> |
= $producto['unidades'] ?> |
@@ -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;
+ ?>
| = htmlspecialchars($data['nombre_display']) ?> |
= $data['unidades'] ?> |
@@ -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