Skip to main content

Architecture Overview

SMAF follows a classic three-tier architecture pattern that separates concerns into distinct layers, promoting maintainability, scalability, and clear separation of responsibilities.

Three-Tier Architecture

1. Presentation Layer (InapescaWeb)

The presentation layer is built with ASP.NET Web Forms and handles all user interface and interaction logic.

Key Components

Web Forms (.aspx)

ASPX pages for user interaction including Solicitudes, Autorizaciones, Comprobaciones, and Pagos

Code-Behind (.aspx.cs)

C# code-behind files containing page-level business logic and event handlers

Telerik Controls

Rich UI components including RadGrid, RadCalendar, RadUpload, and RadTreeView

Master Pages

Consistent layout and navigation across the application

Directory Structure

InapescaWeb/
├── Solicitudes/          # Commission request forms
│   ├── Solicitud_Comision.aspx
│   └── SolicitudPSP.aspx
├── Autorizaciones/       # Authorization workflows
│   └── Comision_Aut.aspx
├── Comprobaciones/       # Expense verification
│   ├── Comision_Comprobacion.aspx
│   └── Comprobacion2017.aspx
├── Pagos/                # Payment processing
│   └── PagaViaticos.aspx
├── Reportes/             # Report generation
├── Catalogos/            # Master data catalogs
├── Styles/               # CSS stylesheets
├── Resources/            # Static resources
└── web.config            # Configuration

Web Configuration

<?xml version="1.0"?>
<configuration>
  <system.web>
    <httpRuntime maxRequestLength="50000" />
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Design, Version=4.0.0.0" />
        <add assembly="System.Web.Extensions, Version=4.0.0.0" />
        <add assembly="System.Windows.Forms, Version=4.0.0.0" />
      </assemblies>
    </compilation>
    
    <pages>
      <controls>
        <add tagPrefix="telerik" 
             namespace="Telerik.Web.UI" 
             assembly="Telerik.Web.UI" />
      </controls>
    </pages>
    
    <httpHandlers>
      <add path="Telerik.Web.UI.WebResource.axd" 
           type="Telerik.Web.UI.WebResource" 
           verb="*" 
           validate="false" />
      <add path="ChartImage.axd" 
           type="Telerik.Web.UI.ChartHttpHandler" 
           verb="*" 
           validate="false" />
    </httpHandlers>
  </system.web>
</configuration>
Connection strings are encrypted using custom encryption (MngEncriptacion) for security. The system supports multiple database connections for different modules (SMAF, DGAIPP, Contratos).

Example Page Implementation

protected void Page_Load(object sender, EventArgs e)
{
    if (!clsFuncionesGral.IsSessionTimedOut())
    {
        if (!IsPostBack)
        {
            // Load navigation menu based on user role
            clsFuncionesGral.LlenarTreeViews(
                dictionary.NUMERO_CERO, 
                tvMenu, 
                false, 
                "Menu", 
                "SMAF", 
                Session["Crip_Rol"].ToString()
            );
            
            Carga_Valores();
            CrearTabla();
        }
    }
    else
    {
        Response.Redirect("../Index.aspx", true);
    }
}

2. Business Logic Layer (InapescaWeb.BRL)

The Business Logic Layer encapsulates all business rules, validation, and coordination between the presentation and data access layers.

Key Manager Classes

InapescaWeb.BRL/
├── MngNegocioComision.cs          # Commission business logic
├── MngNegocioComprobacion.cs      # Expense verification logic
├── MngNegocioPago.cs              # Payment processing
├── MngNegocioUsuarios.cs          # User management
├── MngNegocioProyecto.cs          # Project management
├── MngNegocioMinistracion.cs      # Advance payment logic
├── MngNegocioTransparencia.cs     # Transparency reporting
└── MngNegocioPermisos.cs          # Permission management

Business Logic Examples

namespace InapescaWeb.BRL
{
    public class MngNegocioComision
    {
        // Insert expense report with fiscal validation
        public static Boolean Inserta_Comprobacion_Comision(
            string psOficio, 
            string psClvOficio, 
            string psComisionado, 
            string psUbicacionComisionado, 
            string psFechaFactura, 
            string psProyecto, 
            string psUbicacionProyecto, 
            string psTipoComprobacion, 
            string psClvConcepto, 
            string psDescripcionConcepto, 
            string psPdf, 
            string psImporte, 
            string psXml, 
            string psMetPago, 
            string psMetPagoUsser, 
            string psObservaciones, 
            string psDocumento, 
            string psTicket, 
            string psUUID, 
            string psPeriodo, 
            string psVersion = ""
        )
        {
            return MngDatosComision.Inserta_Comprobacion_Comision(
                psOficio, psClvOficio, psComisionado, 
                psUbicacionComisionado, psFechaFactura, psProyecto, 
                psUbicacionProyecto, psTipoComprobacion, psClvConcepto, 
                psDescripcionConcepto, psPdf, psImporte, psXml, 
                psMetPago, psMetPagoUsser, psObservaciones, 
                psDocumento, psTicket, psUUID, psPeriodo, psVersion
            );
        }
        
        // Retrieve commissions for transparency
        public static List<Comision> Lista_ComisionesTransparencia(
            string psYear
        )
        {
            return MngDatosComision.Lista_ComisionesTransparencia(psYear);
        }
        
        // Check for overlapping commissions
        public static bool Comision_Extraordinaria(
            string psUsuario, 
            string psFechaInicio, 
            string psFechaFinal, 
            string psOpcion
        )
        {
            return MngDatosComision.Comision_Extraordinaria(
                psUsuario, psFechaInicio, psFechaFinal, psOpcion
            );
        }
        
        // Calculate accumulated travel days
        public static string Dias_Acumulados(
            string psComisionado,
            string psPeriodo
        )
        {
            return MngDatosComision.Dias_Acumulados(
                psComisionado, psPeriodo
            );
        }
    }
}
The BRL layer should never directly access the database. All data operations must go through the DAL layer to maintain proper separation of concerns.

3. Data Access Layer (InapescaWeb.DAL)

The Data Access Layer handles all database interactions and data persistence logic.

Key Data Manager Classes

InapescaWeb.DAL/
├── MngConexion.cs                 # Database connection management
├── MngDatosComision.cs            # Commission data operations
├── MngDatosUsuarios.cs            # User data operations
├── MngDatosComprobacion.cs        # Expense data operations
├── MngDatosPagos.cs               # Payment data operations
├── MngDatosProyecto.cs            # Project data operations
├── MngEncriptacion.cs             # Encryption utilities
└── clsFunciones.cs                # Common data functions

Database Connection Management

using MySql.Data.MySqlClient;
using System.Configuration;
using System.Data;

namespace InapescaWeb.DAL
{
    public class MngConexion
    {
        public static MySqlConnection ConexionMysql;
        
        // Get main SMAF database connection
        public static MySqlConnection getConexionMysql()
        {
            string CadenaConexionEncriptada = 
                ConfigurationManager.AppSettings["localhost"];
            
            string CadenaConexion = 
                MngEncriptacion.decripString(CadenaConexionEncriptada);
            
            ConexionMysql = new MySqlConnection(CadenaConexion);
            return ConexionMysql;
        }
        
        // Get DGAIPP module connection
        public static MySqlConnection getConexionMysql_dgaipp()
        {
            string CadenaConexionEncriptada = 
                ConfigurationManager.AppSettings["localhost_dgaipp"];
            
            string CadenaConexion = 
                MngEncriptacion.decripString(CadenaConexionEncriptada);
            
            ConexionMysql1 = new MySqlConnection(CadenaConexion);
            return ConexionMysql1;
        }
        
        // Dispose connection properly
        public static void disposeConexion()
        {
            ConexionMysql.Close();
            ConexionMysql.Dispose();
        }
    }
}

Entity Layer (InapescaWeb.Entidades)

Domain entities represent business objects and data structures.

Core Entities

Usuario

User information including credentials, role, location, and personal data

Comision

Travel commission with all details: dates, destination, budget, approvals

comprobacion

Expense verification records with receipts and amounts

Pagos

Payment records with bank details and transaction information
namespace InapescaWeb.Entidades
{
    public class Usuario
    {
        // Authentication
        public string Usser { get; set; }
        public string Password { get; set; }
        public string Rol { get; set; }
        public string Nivel { get; set; }
        
        // Personal Information
        public string Nombre { get; set; }
        public string ApPat { get; set; }
        public string ApMat { get; set; }
        public string RFC { get; set; }
        public string CURP { get; set; }
        public string Email { get; set; }
        
        // Organizational
        public string Secretaria { get; set; }
        public string Organismo { get; set; }
        public string Ubicacion { get; set; }
        public string Area { get; set; }
        public string Puesto { get; set; }
        public string Cargo { get; set; }
        
        // Address
        public string calle { get; set; }
        public string numext { get; set; }
        public string num_int { get; set; }
        public string colonia { get; set; }
        public string delegacion { get; set; }
        public string Estado { get; set; }
    }
}

Technology Stack

ASP.NET 4.0

Web application framework with Web Forms

C# .NET

Primary programming language

MySQL

Relational database for data persistence

Telerik UI

Rich web UI component suite

IIS

Web server for hosting

Visual Studio

Development environment

Key Technologies

ComponentTechnologyPurpose
Web FrameworkASP.NET Web Forms 4.0Server-side web application framework
LanguageC#Business logic and data access
DatabaseMySQLData persistence and storage
ORM/Data AccessMySql.Data.MySqlClientDatabase connectivity
UI ComponentsTelerik RadControlsRich UI widgets (Grid, Calendar, Upload, etc.)
ReportingMicrosoft ReportViewerPDF report generation
Document ProcessingXML/PDF parsingFiscal receipt validation (CFDI)
EncryptionCustom (MngEncriptacion)Connection string and password encryption

Component Interaction Flow

Example: Creating a Commission Request

Example: Processing Payment

Security Architecture

Authentication & Authorization

protected void btnAceptar_Click(object sender, EventArgs e)
{
    // Input validation with regex
    if (!clsFuncionesGral.Exp_Regular(txtUsuario.Text))
    {
        if (!clsFuncionesGral.Exp_Regular(txtPassword.Text))
        {
            Entidades.Login objLogin = new Entidades.Login();
            
            // Encrypt credentials before transmission
            objLogin.Usuario = MngEncriptacion.encryptString(
                clsFuncionesGral.ConvertMayus(txtUsuario.Text)
            );
            objLogin.Password = MngEncriptacion.encryptString(
                clsFuncionesGral.ConvertMayus(txtPassword.Text)
            );
            
            Valida_Session(objLogin);
        }
    }
}

public void Valida_Session(Entidades.Login objLogin)
{
    Entidades.Usuario oUsuario = MngNegocioLogin.Acceso_Smaf(
        objLogin.Ubicacion, 
        objLogin.Usuario, 
        objLogin.Password
    );
    
    if (!oUsuario.Usser.Equals("0"))
    {
        // Create secure session
        Session.Timeout = 30;
        Session["Crip_Usuario"] = oUsuario.Usser;
        Session["Crip_Rol"] = oUsuario.Rol;
        Session["Crip_Ubicacion"] = oUsuario.Ubicacion;
        // ... store user context
        
        Response.Redirect("Home/Home.aspx", true);
    }
}

Security Features

  • Encrypted connection strings using custom encryption
  • SQL injection prevention via parameterized queries
  • Input validation with regular expressions
  • Session timeout enforcement (30 minutes)
  • Role-based access control throughout the application
  • X-Frame-Options header to prevent clickjacking
  • File upload restrictions (50MB max, validation)

Project Structure

The complete solution structure in Visual Studio:
InapescaWeb.sln
├── InapescaWeb (Web Application)
│   ├── Presentation layer (.aspx pages)
│   ├── Code-behind files (.aspx.cs)
│   └── Configuration (web.config)
├── InapescaWeb.BRL (Class Library)
│   └── Business logic managers
├── InapescaWeb.DAL (Class Library)
│   └── Data access managers
└── InapescaWeb.Entidades (Class Library)
    └── Domain entities
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InapescaWeb", 
  "InapescaWeb\InapescaWeb.csproj", "{090B5AA3-82FB-4607-BEE8-38EBDA114B4E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InapescaWeb.Entidades", 
  "InapescaWeb.Entidades\InapescaWeb.Entidades.csproj", 
  "{6B711C7C-3272-43FC-BB0C-A99E644DF90B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InapescaWeb.BRL", 
  "InapescaWeb.BRL\InapescaWeb.BRL.csproj", "{9E452915-86A4-4499-B7C6-EDB42B6FF5EE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InapescaWeb.DAL", 
  "InapescaWeb.DAL\InapescaWeb.DAL.csproj", "{1211AE21-A6A2-42F4-A400-BCC288C0D4A9}"
EndProject

Database Architecture

SMAF uses MySQL as its relational database with the following characteristics:

Database Structure

  • Stored Procedures: Business logic encapsulated in database
  • Multiple Databases: Separate databases for SMAF, DGAIPP, and Contratos modules
  • Encrypted Connections: All connection strings encrypted in configuration

Key Database Operations

// Example stored procedure call
cmd = new MySqlCommand("sp_obtiene_comisiones", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@periodo", psPeriodo);
cmd.Parameters.AddWithValue("@usuario", psUsuario);

File System Integration

SMAF stores documents in the file system:
  • XML files: CFDI fiscal receipts (v3.3, v4.0)
  • PDF files: Receipt PDFs, reports, official documents
  • Upload directories: Organized by year, project, and commission

Performance Considerations

Connection Pooling

MySQL connection pooling for efficient database access

Telerik CDN

UI components served from CDN to reduce server load

Session State

In-memory session management with 30-minute timeout

File Streaming

Large files served via streaming to minimize memory usage

Next Steps

Development Guide

Set up your development environment and build the project

API Reference

Detailed API documentation for all layers

Database Schema

Complete database schema and stored procedures

Deployment

Deploy SMAF to IIS production environment

Build docs developers (and LLMs) love