diff --git a/DATA_STRUCTURE.md b/DATA_STRUCTURE.md index 1f7cda6..ce36205 100644 --- a/DATA_STRUCTURE.md +++ b/DATA_STRUCTURE.md @@ -17,8 +17,7 @@ DATA/ │ │ ├── aulario_abc123.json │ │ └── aulario_xyz456.json │ └── SuperCafe/ # SuperCafe data (per centro) - │ ├── Personas.json # People directory - │ ├── Menu.json # Menu items / categories + │ ├── Menu.json # Menu items / categories (optional) │ └── Comandas/ # One JSON file per order │ └── sc.json └── centro2/ @@ -28,14 +27,10 @@ DATA/ ## File Examples -### SuperCafe Persons (DATA/entreaulas/Centros/{centro_id}/SuperCafe/Personas.json) +### SuperCafe (persons come from the existing Alumnos system) -```json -{ - "persona1": { "Nombre": "Ana García", "Region": "Clase A" }, - "persona2": { "Nombre": "Luis Martínez", "Region": "Clase B" } -} -``` +Persons are loaded automatically from the aulario Alumnos directories — no separate configuration file is needed. +See the **Aulario Student Names** section for the alumnos data format. ### SuperCafe Menu (DATA/entreaulas/Centros/{centro_id}/SuperCafe/Menu.json) @@ -57,13 +52,14 @@ DATA/ ```json { "Fecha": "2024-01-15", - "Persona": "persona1", + "Persona": "aulario_abc123:Juan", "Comanda": "1x Café, 1x Bocadillo", "Notas": "Sin azúcar", "Estado": "Pedido" } ``` +`Persona` is stored as `{aulario_id}:{alumno_name}` and resolved to a display name at render time. Order statuses: `Pedido`, `En preparación`, `Listo`, `Entregado`, `Deuda`. A person with 3 or more orders in `Deuda` status cannot place new orders. diff --git a/public_html/entreaulas/supercafe.php b/public_html/entreaulas/supercafe.php index 9703f07..d996528 100644 --- a/public_html/entreaulas/supercafe.php +++ b/public_html/entreaulas/supercafe.php @@ -17,6 +17,53 @@ function sc_safe_order_id($value) return preg_replace('/[^a-zA-Z0-9_-]/', '', basename((string)$value)); } +/** + * Load personas from the existing Alumnos system. + * Returns array keyed by "{aulario_id}:{alumno_name}" with + * ['Nombre', 'Region' (aulario display name), 'AularioID', 'HasPhoto'] entries. + */ +function sc_load_personas_from_alumnos($centro_id) +{ + $aularios_path = "/DATA/entreaulas/Centros/$centro_id/Aularios"; + $personas = []; + if (!is_dir($aularios_path)) { + return $personas; + } + foreach (glob("$aularios_path/*.json") ?: [] as $aulario_file) { + $aulario_id = basename($aulario_file, '.json'); + $aulario_data = json_decode(file_get_contents($aulario_file), true); + $aulario_name = $aulario_data['name'] ?? $aulario_id; + $alumnos_path = "$aularios_path/$aulario_id/Alumnos"; + if (!is_dir($alumnos_path)) { + continue; + } + foreach (glob("$alumnos_path/*/", GLOB_ONLYDIR) ?: [] as $alumno_dir) { + $alumno_name = basename($alumno_dir); + $key = $aulario_id . ':' . $alumno_name; + $personas[$key] = [ + 'Nombre' => $alumno_name, + 'Region' => $aulario_name, + 'AularioID' => $aulario_id, + 'HasPhoto' => file_exists("$alumno_dir/photo.jpg"), + ]; + } + } + return $personas; +} + +/** + * Return a human-readable label for a persona key. + * Falls back to showing the raw stored value for legacy orders. + */ +function sc_persona_label($persona_key, $personas) +{ + if (isset($personas[$persona_key])) { + $p = $personas[$persona_key]; + return $p['Nombre'] . ' (' . $p['Region'] . ')'; + } + return $persona_key; +} + $centro_id = safe_centro_id_sc($_SESSION['auth_data']['entreaulas']['centro'] ?? ''); if ($centro_id === '') { require_once "_incl/pre-body.php"; @@ -37,6 +84,7 @@ $estados_colores = [ ]; $can_edit = in_array('supercafe:edit', $_SESSION['auth_data']['permissions'] ?? []); +$personas = sc_load_personas_from_alumnos($centro_id); // Handle POST actions (requires edit permission) if ($_SERVER['REQUEST_METHOD'] === 'POST' && $can_edit) { @@ -139,7 +187,7 @@ require_once "_incl/pre-body.php"; ?> - + @@ -203,7 +251,7 @@ require_once "_incl/pre-body.php"; - + diff --git a/public_html/entreaulas/supercafe_edit.php b/public_html/entreaulas/supercafe_edit.php index b6dae09..6c2172c 100644 --- a/public_html/entreaulas/supercafe_edit.php +++ b/public_html/entreaulas/supercafe_edit.php @@ -31,14 +31,45 @@ define('SC_MAX_DEBTS', 3); $valid_statuses = ['Pedido', 'En preparación', 'Listo', 'Entregado', 'Deuda']; -function sc_load_personas($sc_base) +/** + * Load personas from the existing Alumnos system (alumnos.php). + * Returns array keyed by "{aulario_id}:{alumno_name}" with + * ['Nombre', 'Region' (aulario display name), 'AularioID'] entries. + * Groups are sorted by aulario name, alumnos sorted alphabetically. + */ +function sc_load_personas_from_alumnos($centro_id) { - $path = "$sc_base/Personas.json"; - if (!file_exists($path)) { - return []; + $aularios_path = "/DATA/entreaulas/Centros/$centro_id/Aularios"; + $personas = []; + if (!is_dir($aularios_path)) { + return $personas; } - $data = json_decode(file_get_contents($path), true); - return is_array($data) ? $data : []; + $aulario_files = glob("$aularios_path/*.json") ?: []; + foreach ($aulario_files as $aulario_file) { + $aulario_id = basename($aulario_file, '.json'); + $aulario_data = json_decode(file_get_contents($aulario_file), true); + $aulario_name = $aulario_data['name'] ?? $aulario_id; + $alumnos_path = "$aularios_path/$aulario_id/Alumnos"; + if (!is_dir($alumnos_path)) { + continue; + } + $alumno_dirs = glob("$alumnos_path/*/", GLOB_ONLYDIR) ?: []; + usort($alumno_dirs, function ($a, $b) { + return strcasecmp(basename($a), basename($b)); + }); + foreach ($alumno_dirs as $alumno_dir) { + $alumno_name = basename($alumno_dir); + // Key uses ':' as separator; safe_id_segment chars [A-Za-z0-9_-] exclude ':' + $key = $aulario_id . ':' . $alumno_name; + $personas[$key] = [ + 'Nombre' => $alumno_name, + 'Region' => $aulario_name, + 'AularioID' => $aulario_id, + 'HasPhoto' => file_exists("$alumno_dir/photo.jpg"), + ]; + } + } + return $personas; } function sc_load_menu($sc_base) @@ -51,7 +82,7 @@ function sc_load_menu($sc_base) return is_array($data) ? $data : []; } -function sc_count_debts($persona_id) +function sc_count_debts($persona_key) { if (!is_dir(SC_DATA_DIR)) { return 0; @@ -60,7 +91,7 @@ function sc_count_debts($persona_id) foreach (glob(SC_DATA_DIR . '/*.json') ?: [] as $file) { $data = json_decode(file_get_contents($file), true); if (is_array($data) - && ($data['Persona'] ?? '') === $persona_id + && ($data['Persona'] ?? '') === $persona_key && ($data['Estado'] ?? '') === 'Deuda') { $count++; } @@ -92,22 +123,30 @@ if (!$is_new && is_readable($order_file)) { } } -$personas = sc_load_personas($sc_base); +$personas = sc_load_personas_from_alumnos($centro_id); $menu = sc_load_menu($sc_base); +// Group personas by aulario for the optgroup picker +$personas_by_aulario = []; +foreach ($personas as $key => $pinfo) { + $personas_by_aulario[$pinfo['Region']][$key] = $pinfo; +} + $error = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { - $persona_id = $_POST['Persona'] ?? ''; - $notas = trim($_POST['Notas'] ?? ''); - $estado = $_POST['Estado'] ?? 'Pedido'; + $persona_key = $_POST['Persona'] ?? ''; + $notas = trim($_POST['Notas'] ?? ''); + $estado = $_POST['Estado'] ?? 'Pedido'; if (!in_array($estado, $valid_statuses, true)) { $estado = 'Pedido'; } - if ($persona_id === '') { - $error = '¡Hay que elegir una persona!'; + // Validate that the submitted persona key exists in the loaded list. + // When no alumnos are configured ($personas is empty), accept any non-empty free-text value. + if ($persona_key === '' || (!empty($personas) && !array_key_exists($persona_key, $personas))) { + $error = '¡Hay que elegir una persona válida!'; } else { // Build comanda string from selected menu items $comanda_parts = []; @@ -122,7 +161,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } } } else { - // No menu configured: accept free-text input $manual = trim($_POST['Comanda_manual'] ?? ''); if ($manual !== '') { $comanda_parts[] = $manual; @@ -130,10 +168,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { } $comanda_str = implode(', ', $comanda_parts); - // Debt check: only for new orders or when changing the person + // Debt check: only for new orders or when the person changes $prev_persona = $order_data['Persona'] ?? ''; - if ($is_new || $prev_persona !== $persona_id) { - $debt_count = sc_count_debts($persona_id); + if ($is_new || $prev_persona !== $persona_key) { + $debt_count = sc_count_debts($persona_key); if ($debt_count >= SC_MAX_DEBTS) { $error = 'Esta persona tiene ' . $debt_count . ' comandas en deuda. No se puede realizar el pedido.'; } @@ -142,7 +180,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($error === '') { $new_data = [ 'Fecha' => date('Y-m-d'), - 'Persona' => $persona_id, + 'Persona' => $persona_key, 'Comanda' => $comanda_str, 'Notas' => $notas, 'Estado' => $is_new ? 'Pedido' : $estado, @@ -192,26 +230,44 @@ require_once "_incl/pre-body.php";
- + + +
+ + Foto de <?= htmlspecialchars($sel_info['Nombre']) ?> +
+ - No hay personas configuradas en - /DATA/entreaulas/Centros//SuperCafe/Personas.json. + No hay alumnos registrados en los aularios de este centro. + Añade alumnos desde + EntreAulas.
@@ -281,3 +337,4 @@ require_once "_incl/pre-body.php"; + diff --git a/public_html/sysadmin/users.php b/public_html/sysadmin/users.php index 5e6a759..ad2585a 100644 --- a/public_html/sysadmin/users.php +++ b/public_html/sysadmin/users.php @@ -192,6 +192,33 @@ switch ($_GET['action'] ?? '') { +
+
+

EntreAulas: Configuración

+
+ + +
+
+ + +
+

Las aulas podrán asignarse tras guardar el usuario.

+
+