ContabilidadISV follows a classic three-tier architecture. The presentation tier is a React 18 + TypeScript single-page application built with Vite. It communicates exclusively through HTTP with the logic tier: an Express.js REST API that enforces authentication, validates inputs, and executes all business rules. The data tier is a Microsoft SQL Server database accessed through a managedDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Medinaallan/ContabilidadISV/llms.txt
Use this file to discover all available pages before exploring further.
mssql connection pool. An optional Electron shell wraps all three tiers into a self-contained Windows desktop application, spawning the backend as a child process and loading the pre-built frontend from the local filesystem.
Frontend
The frontend lives infrontend/ and is scaffolded with Vite. TypeScript is used throughout. Tailwind CSS handles styling; lucide-react provides icons; date-fns handles locale-aware date formatting for Spanish (Honduras).
API client
frontend/src/services/api.ts exports an Axios instance configured with:
- Base URL detection: In a browser dev session the base URL is
/api(proxied by Vite tolocalhost:3002). When running inside Electron,window.electron.env.API_URLis read from the preload script to point directly athttp://localhost:3002/api. - Request interceptor: Reads the JWT from
localStorageand injects it asAuthorization: Bearer <token>on every request. - Response interceptor: On
401 Unauthorized, clearslocalStorageand redirects to/login.
Auth context
frontend/src/contexts/AuthContext provides user, login, and logout to the entire component tree. useAuth() is the primary hook consumed by DashboardPage and route guards.
Navigation sections
DashboardPage.tsx is the authenticated shell. It renders a top navigation bar and swaps the content area by setting activeSection. The available sections and their access rules are:
| Section key | Label | Minimum role |
|---|---|---|
home | Inicio | user |
upload | Crear Consolidación | user |
history | Historial | user |
reports | Reportes | user |
clients-view | Ver y Añadir (Clientes) | user |
csv-upload | Cargar desde CSV | admin |
logs | Logs del Sistema | admin |
users | Gestión de Usuarios | admin |
system-config | Soporte técnico | admin |
Backend
The backend lives inbackend/ and is an Express.js application. It is started with node backend/server.js (or npm run dev inside backend/ for nodemon hot-reload).
Route map
| Mount path | File | Description |
|---|---|---|
/api/auth | routes/auth.js | Login, register, profile, token validation, logout, login history (admin) |
/api/consolidaciones | routes/consolidaciones.js | CRUD for Generales and Hoteles consolidations, filtered history |
/api/clientes | routes/clientes.js | Client CRUD, status toggle, hard/soft delete, stats, logo upload |
/api/users | routes/users.js | User management (admin) |
/api/files | routes/files.js | File upload, download, history, consolidated data retrieval |
/api/reports | routes/reports.js | Dashboard summary, totals, metrics, ranking, period summaries |
/api/logs | routes/logs.js | System log retrieval and creation |
/api/admin | routes/admin.js | Admin-only utilities |
Auth middleware
backend/src/middleware/auth.js exports two functions used across all protected routes:
authenticateToken— Verifies theAuthorization: Bearer <token>header usingJWT_SECRET. Attaches the decoded payload toreq.user. Returns401if the token is absent or invalid.requireRole(roles[])— Called afterauthenticateToken. Returns403ifreq.user.roleis not in the permitted roles array. Example usage fromauth.js:
Input validation
All mutation routes useexpress-validator body() validators. For example, the login route requires username (min 3 chars) and password (non-empty); the register route additionally validates email format and enforces a minimum 6-character password.
Connection pooling
backend/src/models/Database_SqlServer.js wraps the mssql library in a singleton Database class. On first use, init() opens a connection pool (sql.connect(config)) and stores it as this.pool. Every subsequent query reuses the pool. Configuration keys read from process.env:
Database
ContabilidadISV uses Microsoft SQL Server. The tables must be created in SQL Server before first use;npm run init-db (backend/scripts/initDatabase.js) then connects and seeds the default admin account.
Tables
| Table | Purpose |
|---|---|
users | Accounts with username, email, password (bcryptjs hash), role (user | admin) |
consolidaciones_generales | Standard ISV consolidations — 55 accounts, Debe/Haber, ISV 15 %, ISV 18 % |
consolidaciones_hoteles | Hotel ISV+IST consolidations — same as Generales plus ist_4 column |
clientes | Client profiles: nombre_empresa, rtn, rubro, representante, telefono, email, direccion, logo_url, activo |
system_logs | Audit trail: user_id, action, description, ip_address, user_agent, created_at |
uploaded_files | Metadata for files uploaded through the file service |
Why two consolidation tables?
consolidaciones_hoteles has an ist_4 column that consolidaciones_generales does not. Storing both types in a single table would require a nullable column and an implicit type discriminator, which makes tax-period queries and export templates more complex. Two dedicated tables keep the schema explicit and the SQL straightforward.
See the Database Configuration guide for migration commands and schema details.
Electron mode
The optional Electron shell packages the entire application into a single Windows executable using electron-builder with an NSIS installer target.How electron/main.js works
- Single-instance lock —
app.requestSingleInstanceLock()prevents duplicate windows. - Backend spawn — In production (packaged) mode,
startBackend()spawnsnode backend/server.jsas a child process, passingPORT=3002via environment. The backend path is resolved fromprocess.resourcesPath/app.asar.unpacked/backend(ASAR unpack path defined inpackage.jsonbuild.asarUnpack). - Window creation —
createWindow()creates aBrowserWindow(1400 × 900, min 1024 × 768) with:nodeIntegration: falseandcontextIsolation: truefor security- A preload script (
electron/preload.js) that exposeswindow.electron.isElectronandwindow.electron.env.API_URLto the renderer
- URL loading — In dev mode, loads
https://localhost:5174; in production, loadsfrontend/dist/index.htmldirectly from the filesystem (viafile://path resolved fromprocess.resourcesPath/app.asar.unpacked/frontend/dist/index.html). - Graceful shutdown —
app.on('before-quit')kills the backend child process before the Electron process exits.
Build commands
dist-electron/. See the Electron deployment guide for signing, icon preparation, and distribution options.
Monorepo directory structure
Environment Configuration
All
backend/.env variables, their defaults, and guidance for production vs. development values.Database Configuration
SQL Server setup, the full schema created by
init-db, and migration strategies.