⚖️ Bascula
El módulo de Báscula del Sistema de Información Integral Beta (SIIB) es una aplicación diseñada para gestionar el proceso de pesaje de vehículos 🚛 que transportan diversos productos, como leche 🥛, forraje 🌾 y otros materiales.
El sistema controla todo el ciclo de vida de una "ficha" de báscula 📄, desde la captura del peso inicial ⚙️ (tara o peso bruto) hasta el segundo pesaje ⚖️ para obtener el peso neto, generando un registro detallado de la operación 🧾.
🎯 Objetivos Principales
- ⚙️ Automatizar el Pesaje: Integrarse directamente con la báscula de hardware para capturar pesos de manera precisa y automática.
- 📄 Generar Fichas de Control: Crear registros (fichas) para cada operación de pesaje, asociando información clave como establo, proveedor/cliente, producto, chofer y placas.
- 🔄 Soportar Múltiples Flujos: Manejar diferentes tipos de fichas con campos específicos, como "Envío de Leche", "Forraje" o "Regular".
- 🧭 Control de Procesos: Administrar el flujo de dos pesadas, mostrando fichas pendientes y calculando el peso total.
- 📊 Generación de Reportes: Ofrecer herramientas para consultar, reportar y exportar el historial de fichas por establo y rango de fechas.
- 🖨️ Impresión y Agrupación: Permitir la reimpresión de fichas y agrupar fichas de envío de leche para un control logístico centralizado.
🏗️ Arquitectura Técnica
El módulo sigue una arquitectura de aplicación web tradicional basada en la plataforma .NET, utilizando el patrón Modelo-Vista-Controlador (MVC).
🗄️ Base de Datos (Modelo)
La persistencia de los datos se realiza en una base de datos SQL Server llamada BETA_CORP.
Las tablas están diseñadas para almacenar la información de las fichas, así como catálogos para establos, artículos, proveedores, etc.
⚙️ Lógica de Negocio (Controlador)
El controlador BASCULAController, escrito en C#, contiene toda la lógica del servidor.
Se encarga de procesar las solicitudes del usuario, interactuar con la base de datos (a través de Entity Framework, como se infiere del uso de db.C_bascula_fichas), y renderizar las vistas.
🖥️ Interfaz de Usuario (Vista)
Las vistas están construidas con Razor (CSHTML).
La interfaz es dinámica y utiliza vistas parciales para cargar diferentes formularios según el tipo de ficha seleccionado por el usuario.
Se apoya en librerías de CSS como Bootstrap y otras personalizadas para el estilo visual.
💻 Interactividad del Cliente (JavaScript)
La lógica del lado del cliente se maneja con JavaScript y jQuery.
Se utiliza AJAX extensivamente para comunicarse con el controlador sin necesidad de recargar la página completa, lo que permite obtener el peso de la báscula, guardar fichas y actualizar dinámicamente el contenido de la página.
🧩 3.1. Base de Datos
El esquema de la base de datos es el núcleo del módulo. Las tablas más importantes son:
🗂️ Tablas Principales
-
📋 C_bascula_fichas:
Tabla transaccional principal que almacena cada registro de pesaje.
Campos clave:id_bascula_ficha(PK)id_establoid_ficha_tipoid_articulo_basculapeso_1,peso_2,peso_t(peso total)fecha_registro,fecha_segunda_pesadatermina(bit que indica si el proceso de dos pesadas concluyó)
-
📘 C_bascula_fichas_tipos:
Catálogo que define los tipos de ficha (ejemplo: Leche, Forraje). -
🏠 C_establos:
Catálogo de los establos donde se realizan los pesajes. -
📦 C_articulos_catalogo:
Catálogo general de productos que pueden ser pesados. -
🔄 C_bascula_codigos_movimientos:
Define los tipos de movimientos (ejemplo: Entrada, Salida) asociados a una operación. -
🚛 C_bascula_lineas_transportistas:
Catálogo para las líneas de transporte.
🔗 Tablas de Relación
Múltiples tablas como:
C_bascula_establos_fichas_tiposC_articulos_catalogo_bascula
Gestionan las relaciones y permisos entre los catálogos.
Las relaciones se establecen mediante Foreign Keys 🔑 para garantizar la integridad referencial de los datos.
##⚙️ 3.2. Lógica del Backend (Controlador: BASCULAController.cs)
El controlador gestiona todas las acciones del servidor. Los métodos más relevantes son los siguientes:
🔹 ActionResult Index()
- Carga la vista principal del módulo.
- Verifica los permisos de sesión del usuario antes de permitir el acceso.
⚖️ string ObtenerPesoBascula(int id_establo)
- Función crítica: Se comunica directamente con un puerto serial (
parametros.puerto) para leer el peso desde el hardware de la báscula. - Utiliza los parámetros de configuración definidos en la tabla
C_bascula_establos_codigos_puertos⚙️, los cuales determinan:- El puerto de conexión.
- El código de lectura.
- Otros parámetros de comunicación necesarios.
🧾 bool GuardarPrimeraPesada(C_bascula_fichas c_ficha)
- Recibe un objeto
C_bascula_fichasdesde la vista. - Asigna los siguientes valores automáticamente:
fecha_registro📅usuario👤activo = true✅
- Guarda el nuevo registro en la base de datos, representando la primera pesada.
🔍 string ConsultarInfoFicha(int ficha, int id_establo)
- Busca una ficha pendiente (
termina == false) en la base de datos. - Realiza una consulta compleja con múltiples JOINs para obtener información relacionada como:
- Nombre del proveedor 🧑🌾
- Artículo 📦
- Establo 🐄
- Serializa el resultado en JSON y lo devuelve al cliente.
⚖️ int GuardarSegundaPesada(...)
- Actualiza una ficha existente con el nuevo
peso_2. - Calcula el peso total:
(peso_t = |peso_1 - peso_2|). - Marca la ficha como terminanada:
(termina = true). - Si la ficha es de tipo leche
(tipo_ficha == 1), además crea registros en las tablas C_envios_leche_d_fichas y C_envios_leche_d_calidad.
📊 PartialViewResult ConsultarReporteFichas(...)
- Devuelve una vista parcial con los datos del reporte de fichas.
- Permite filtrar por establo y rango de fechas para análisis o auditorías.
🧾 PartialViewResult ImpresionFichaPDF(...)
- Prepara los datos y devuelve la vista parcial
_PDFBascula,
que sirve como plantilla para la impresión del ticket 🖨️.
🧩 PartialViewResult ConsultarFormatoFichaBascula(int idtipoficha, int pesada)
- Devuelve la vista parcial del formulario correspondiente, por ejemplo:
_FichaLechePp_FichaForrajeSp- La vista cargada depende del tipo de ficha y si corresponde a la primera o segunda pesada ⚖️.
🖥️ 3.3. Interfaz de Usuario (Vistas Razor)
La interfaz se compone de una vista principal y múltiples vistas parciales, diseñadas para mantener la modularidad y la claridad del sistema.
📄 Index.cshtml
- Página principal del módulo de báscula.
- Estructura: Utiliza un sistema de pestañas (tabs) para separar las funcionalidades:
- 🟢 PRIMERA PESADA
- 🔵 SEGUNDA PESADA
- 🟣 REPORTE DE FICHAS
- 🟠 REIMPRESIÓN
- Carga dinámica: Contiene
divsvacíos (por ejemplo,<div id="div_tipo_ficha_pp"></div>) que son poblados dinámicamente con vistas parciales mediante JavaScript ⚙️.
🧩 Vistas de Formulario (_FichaTipoPpSp.cshtml)
- Existen diferentes vistas parciales para cada combinación de tipo de ficha y número de pesada, por ejemplo:
_FichaLechePp_FichaForrajeSp
- Pp (Primera Pesada):
- Contiene campos de entrada (
<input>,<select>) 📝 - Permite crear una nueva ficha desde cero.
- Contiene campos de entrada (
- Sp (Segunda Pesada):
- Muestra la mayoría de los campos como solo lectura (readonly) 🔒
- Habilita únicamente los campos necesarios para completar el proceso de la segunda pesada ⚖️.
🧾 _PDFBascula.cshtml
- Plantilla HTML para generar el ticket impreso 🖨️.
- Diseño:
- Muestra la información de la ficha de manera clara y estructurada.
- Incluye el logo de la empresa, los detalles del pesaje y los pesos registrados.
- Duplicado:
- Diseñada para imprimir dos copias en la misma hoja:
- 📜 Original
- 🚛 Copia Chofer
- Diseñada para imprimir dos copias en la misma hoja:
📊 _FichasReporte.cshtml y _FichasPendientes.cshtml
- Son vistas parciales que renderizan tablas HTML con los datos de las fichas consultadas.
- Estas vistas pueden mostrarse directamente en la interfaz principal o dentro de un modal emergente.
- Permiten visualizar fichas pendientes, completadas o filtradas según las necesidades del usuario 🔍.
⚙️ 3.4. Lógica del Cliente (JavaScript)
El archivo de JavaScript orquesta toda la interacción del usuario con el sistema 🧠💻.
A través de llamadas AJAX, validaciones y manipulación del DOM, se logra una experiencia fluida sin recargar la página.
🧩 Funciones Principales
- 🧲 ObtenerPesoBascula(pesada):
- Llama al método del controlador vía AJAX para leer el peso desde el hardware ⚖️.
- Muestra el valor obtenido en el campo de texto correspondiente en la interfaz.
- 💾 GuardarPrimeraPesada(primera_pesada):
- Recopila todos los datos del formulario.
- Realiza validaciones del lado del cliente (por ejemplo, campos obligatorios ✅).
- Construye un objeto
c_fichay lo envía al controlador para ser guardado en la base de datos.
- 📥 GuardarSegundaPesada(segunda_pesada, peso_total):
- Similar a la función anterior, pero enfocada en el proceso de la segunda pesada.
- Calcula el peso total y envía los datos al método correspondiente del controlador ⚙️.
- 🔍 ConsultarInfoFicha(ficha_bascula):
- Obtiene el ID de la ficha y llama al controlador para consultar sus datos.
- Si la consulta tiene éxito, rellena automáticamente los campos del formulario de la segunda pesada 🧾.
- 🧱 ConsultarFormatoFichaBascula(idtipoficha, pesada):
- Función clave para la interfaz dinámica.
- Se activa al cambiar el tipo de ficha, cargando la vista parcial adecuada en el
divcorrespondiente 📄.
- 📊 ConsultarReporteFichas():
- Llama al controlador vía AJAX para obtener los datos del reporte.
- Renderiza los resultados en una tabla HTML e inicializa el plugin DataTable para:
- 🔹 Paginación
- 🔹 Búsqueda
- 🔹 Exportación de datos
- 🖨️ ImpresionFichaPDF(ficha) y ♻️ ReImpresionFichaPDF(modo):
- Abren una nueva ventana del navegador 🌐.
- Cargan el HTML del ticket devuelto por el controlador.
- Invocan la función de impresión nativa del navegador (
newTab.print()) para generar la ficha física 📑.
🔄 4. Flujos de Trabajo Principales
El módulo de Báscula del sistema SIIB se compone de dos flujos operativos principales:
la Primera Pesada 🏗️ y la Segunda Pesada ⚖️.
Ambos procesos están diseñados para garantizar precisión, trazabilidad y control total del pesaje.
🚛 1. Proceso de Primera Pesada
1️⃣ Selección Inicial
El usuario selecciona el Establo y el Tipo de Ficha (por ejemplo: Leche, Forraje, etc.).
2️⃣ Carga del Formulario
El sistema carga dinámicamente el formulario correspondiente según el tipo de ficha seleccionado.
3️⃣ Captura de Datos
El usuario completa la información requerida:
- 🧾 Proveedor
- 📦 Artículo
- 🚚 Chofer
- 🪪 Placas del vehículo
4️⃣ Obtención del Peso
El usuario presiona el botón “Obtener peso”.
El sistema se comunica directamente con la báscula física ⚙️ y muestra el valor capturado en pantalla.
5️⃣ Creación de la Ficha
El usuario presiona “Crear ficha”.
- Los datos se validan en el cliente.
- Se envían al servidor para ser registrados en la tabla C_bascula_fichas.
- El campo
terminase establece en false, indicando que el proceso aún no está completo.
⚖️ 2. Proceso de Segunda Pesada
1️⃣ Acceso a la Sección
El usuario navega a la pestaña “Segunda Pesada”.
2️⃣ Selección de Ficha Pendiente
Puede buscar una ficha por su número o seleccionarla de la lista de fichas pendientes.
3️⃣ Carga de Información
El sistema carga la información de la ficha en modo de solo lectura 🔒, permitiendo únicamente las acciones necesarias.
4️⃣ Captura del Segundo Peso
El usuario presiona “Obtener peso”, y el sistema toma el peso actual desde la báscula.
5️⃣ Cálculo Automático del Peso Neto
El sistema calcula y muestra el peso total (peso neto) 📏 de manera automática.
6️⃣ Finalización de la Ficha
Al presionar “Segunda Pesada”:
- Se actualiza el registro en la base de datos.
- Se guardan los campos
peso_2,peso_t. - El campo
terminacambia a true, marcando la ficha como finalizada ✅.
7️⃣ Impresión Automática del Ticket
El sistema genera e imprime el ticket físico de la ficha completada 🖨️ con todos los detalles del pesaje.
⚙️ 5. Puntos Clave y Consideraciones
-
🧩 Dependencia de Hardware:
El sistema depende críticamente de la conexión con la báscula a través de un puerto serial.
Fallos en esta comunicación impedirán el registro de pesos ⚠️. -
🔐 Permisos de Usuario:
La visibilidad de las pestañas y funcionalidades está controlada por un sistema de permisos basado en la sesión del usuario
(por ejemplo:permisos.Contains(...)) 👥. -
🧠 Lógica de Negocio Hardcodeada:
Existe lógica específica en el código, como la asignación deno_pozobasada en elid_establo
(ejemplo:if (id_establo == 1) { no_pozo = 1; }).
Esta lógica podría externalizarse a tablas de configuración para una mayor flexibilidad ⚙️. -
🧯 Manejo de Errores:
En el lado del cliente, los errores se manejan principalmente mediante mensajesiziToast🍞.
En el servidor, se utilizan bloquestry-catchque a menudo retornan solo un valor booleano o un string vacío en caso de fallo 🧩.