Appearance
Categoria IVA - Documentación Técnica Backend
⚠️ DOCUMENTACIÓN RETROSPECTIVA - Generada a partir de código implementado el 2026-02-11
Módulo: Ventas Tipo: Resource (solo lectura) Fecha: 2026-02-11
Referencia a Requisitos de Negocio
Esta documentación técnica implementa los requisitos definidos en:
Arquitectura Implementada
Capas del Sistema
El módulo de Categoria IVA implementa una arquitectura simplificada de 2 capas (sin Service Layer) dado que es un recurso de solo lectura sin lógica de negocio:
API Layer (Route + Controller)
↓
Model Layer (Data Access)
↓
Database Layer (PostgreSQL)Justificación: Al tratarse de un recurso de solo lectura sin validaciones de negocio ni transacciones, no se requiere Service Layer. El Controller invoca directamente al Model.
Archivos Implementados
| Capa | Archivo | Responsabilidad |
|---|---|---|
| Route | backend/categoria-iva.php | Endpoint legacy, routing manual |
| Controller | controller/modulo-venta/CategoriaIvaController.php | HTTP handling, respuestas JSON |
| Model | models/modulo-venta/CategoriaIva.php | Data access, queries |
| DTO | Resources/Venta/CategoriaIva.php | Transferencia de datos |
| Migration | migrations/tenancy/20240823200722_new_table_aliva.php | Schema de base de datos |
| Seed | migrations/seeds/tenancy/Aliva.php | Datos de referencia ARCA |
API Endpoints
GET /backend/categoria-iva.php
Descripción: Endpoint legacy para consulta de categorías de IVA.
Autenticación: JWT requerido (middleware global)
Headers:
Authorization: Bearer {jwt_token}X-Schema: {schema}(opcional, para multi-tenancy)
Operación: Listar todas las categorías
Request:
http
GET /backend/categoria-iva.php HTTP/1.1
Content-Type: application/json
{}Response 200 OK:
json
{
"status": 200,
"message": "Datos recibidos correctamente.",
"data": [
{
"codigo": 5,
"nombre": "IVA 21 %",
"porcentaje": 21.00
},
{
"codigo": 3,
"nombre": "Exento",
"porcentaje": 0.00
},
{
"codigo": 4,
"nombre": "IVA 10.50 %",
"porcentaje": 10.50
}
]
}Operación: Obtener categoría por código
Request:
http
GET /backend/categoria-iva.php HTTP/1.1
Content-Type: application/json
{
"codigo": 5
}Response 200 OK:
json
{
"status": 200,
"message": "Datos recibidos correctamente.",
"data": {
"codigo": 5,
"nombre": "IVA 21 %",
"porcentaje": 21.00
}
}Response 404 Not Found:
json
{
"error": "Not Found"
}Operación: Obtener categoría por porcentaje
Request:
http
GET /backend/categoria-iva.php HTTP/1.1
Content-Type: application/json
{
"porcentaje": 21.00
}Response 200 OK:
json
{
"status": 200,
"message": "Datos recibidos correctamente.",
"data": {
"codigo": 5,
"nombre": "IVA 21 %",
"porcentaje": 21.00
}
}Response 404 Not Found:
json
{
"error": "Not Found"
}Códigos de Estado HTTP
| Código | Uso |
|---|---|
| 200 | Consulta exitosa (getAll, getOne) |
| 401 | No autenticado (sin JWT o JWT inválido) |
| 404 | Categoría no encontrada (código/porcentaje inexistente) |
| 500 | Error interno del servidor |
Capa de Controller
CategoriaIvaController
Archivo: controller/modulo-venta/CategoriaIvaController.php
Namespace: App\controller\Venta
Extiende: App\controller\Controller
Dependencias
App\models\Venta\CategoriaIva(Model)PDO(Database connection)
Métodos Implementados
__construct(PDO $conn)
Inicializa el controller con la conexión de base de datos y crea instancia del model.
Parámetros:
$conn: Conexión PDO configurada con el schema correcto
getAll(): array
Retorna todas las categorías de IVA.
Retorna: CategoriaIvaDTO[]
Propósito: Listar el catálogo completo de alícuotas de IVA.
Lógica:
- Invoca
$this->model->getAll() - Retorna array de DTOs
getOne(array $option): ?CategoriaIvaDTO
Retorna una categoría de IVA por código o porcentaje.
Parámetros:
$option['codigo']: int (opcional) - Código ARCA$option['porcentaje']: float (opcional) - Porcentaje de alícuota
Retorna: CategoriaIvaDTO|null
Lógica:
- Si existe
$option['porcentaje'], busca por porcentaje - Si existe
$option['codigo'], busca por código - Si no existe ninguno, lanza
NotFoundexception - Retorna DTO o null si no encuentra
Nota: Prioriza porcentaje sobre código si ambos están presentes.
Capa de Model
CategoriaIva
Archivo: models/modulo-venta/CategoriaIva.php
Namespace: App\models\Venta
Extiende: App\models\Model
Tabla: aliva
Métodos Implementados
getAll(): array
Obtiene todas las categorías de IVA.
SQL:
sql
SELECT codigo, nombre, porcentaje
FROM alivaRetorna: CategoriaIvaDTO[] (array vacío si no hay registros)
Mapeo: Usa CategoriaIvaDTO::fromArray() para mapear cada fila
Nota: No filtra por deleted_at porque la tabla no tiene soft deletes (dato de referencia fiscal).
getByCodigo(int $codigo): ?CategoriaIvaDTO
Obtiene categoría por código ARCA.
Parámetros:
$codigo: Código oficial de ARCA (ej: 5 para IVA 21%)
SQL:
sql
SELECT codigo, nombre, porcentaje
FROM aliva
WHERE codigo = :codigoRetorna: CategoriaIvaDTO|null
Uso: Búsqueda por identificador oficial de ARCA en procesos de facturación.
getByPorcentaje(float $porcentaje): ?CategoriaIvaDTO
Obtiene categoría por porcentaje de alícuota.
Parámetros:
$porcentaje: Porcentaje de IVA (ej: 21.00)
SQL:
sql
SELECT codigo, nombre, porcentaje
FROM aliva
WHERE porcentaje = :porcentajeRetorna: CategoriaIvaDTO|null
Uso: Importación de productos cuando se conoce el porcentaje pero no el código ARCA.
Capa de DTO (Resources)
CategoriaIva DTO
Archivo: Resources/Venta/CategoriaIva.php
Namespace: App\Resources\Venta
Extiende: App\Resources\DTO
Propiedades
| Propiedad | Tipo | Validación | Descripción |
|---|---|---|---|
codigo | int | required|integer | Código oficial ARCA |
porcentaje | float | required|numeric | Porcentaje de alícuota |
nombre | string | required|max:100 | Nombre descriptivo |
Constructor
Valida los datos contra las reglas definidas y asigna propiedades.
Validaciones automáticas:
- Campos requeridos no pueden ser null
codigodebe ser enteroporcentajedebe ser numériconombremáximo 100 caracteres
Esquema de Base de Datos
Tabla: aliva
Nivel Multi-Tenancy: EMPRESA (schema public)
Justificación: Las categorías de IVA son definidas por ARCA (organismo fiscal) y son las mismas para todas las sucursales y cajas de una empresa. No varían por ubicación.
Habilitación: Solo se crea si módulo Ventas o Compras está habilitado.
Schema SQL
sql
CREATE TABLE aliva (
codigo INTEGER NOT NULL PRIMARY KEY,
nombre VARCHAR(100) NOT NULL,
porcentaje DECIMAL(5, 2) NOT NULL
);Columnas
| Campo | Tipo | Constraints | Descripción |
|---|---|---|---|
codigo | INTEGER | PRIMARY KEY NOT NULL | Código oficial ARCA (3, 4, 5, 6, 8, 9) |
nombre | VARCHAR(100) | NOT NULL | Nombre descriptivo ("IVA 21 %", "Exento", etc.) |
porcentaje | DECIMAL(5,2) | NOT NULL | Porcentaje (0.00, 2.50, 5.00, 10.50, 21.00, 27.00) |
Índices
- PRIMARY KEY:
codigo
No se requieren índices adicionales dado el bajo volumen de datos (6 registros conocidos).
Foreign Keys
Ninguna. Esta tabla no tiene relaciones FK de entrada.
Tablas que referencian a aliva:
producto- Productos tienen categoría de IVAitems_factura- Items de factura pueden tener código de IVA
Constraints
Ninguno adicional. La validación de integridad se realiza a nivel de aplicación.
Datos de Referencia (Seed)
Los registros se cargan automáticamente vía seed Aliva.php:
| Código ARCA | Nombre | Porcentaje |
|---|---|---|
| 3 | Exento | 0.00 |
| 4 | IVA 10.50 % | 10.50 |
| 5 | IVA 21 % | 21.00 |
| 6 | IVA 27 % | 27.00 |
| 8 | IVA 5 % | 5.00 |
| 9 | IVA 2.5 % | 2.50 |
Origen de datos: Resolución General 5616/2024 ARCA (Administración Federal de Ingresos Públicos de Argentina).
Multi-Tenancy
Nivel de Aislamiento
EMPRESA (public schema): Datos compartidos por todas las sucursales y cajas.
Razón: Las alícuotas de IVA son definidas por normativa fiscal nacional y no varían por ubicación geográfica.
Configuración en Migration
php
protected function getDefaultLevels(): array
{
return [self::LEVEL_EMPRESA];
}Header X-Schema
El endpoint respeta el header X-Schema para multi-tenancy, pero siempre consulta los datos del schema public (empresa) independientemente del schema del usuario.
Implicación: No importa si el usuario está en suc0001 o suc0002, todos ven las mismas categorías de IVA.
Validaciones
Nivel 1: Validación Estructural
NO IMPLEMENTADA - El endpoint legacy no tiene Validator middleware.
⚠️ Observación técnica: El endpoint acepta cualquier estructura de JSON sin validación previa. La validación ocurre en el DTO.
Nivel 2: Validación de DTO
Implementada en CategoriaIva DTO mediante método validate() heredado.
Reglas:
codigo:required|integerporcentaje:required|numericnombre:required|max:100
Comportamiento: Si un campo no cumple las reglas, el DTO lanza excepción durante construcción.
Nivel 3: Validación de Negocio
NO APLICA - Recurso de solo lectura sin validaciones de negocio.
Puntos de Integración
Consumidores Internos
Módulo de Productos
Uso: Asignación de categoría IVA a productos.
Método usado: getByCodigo(int $codigo)
Contexto: Al crear/editar un producto, se valida que el código de IVA exista.
Módulo de Facturación Electrónica
Uso: Construcción de requests ARCA para facturación.
Trait: Membresia\Domain\Facturacion\Builder\Traits\ArcaAlicuotasTrait
Método usado: findCategoriaByPorcentaje(array $categorias, float $porcentaje)
Contexto: Durante la facturación masiva, se buscan categorías de IVA para armar alícuotas en el request ARCA.
Nota: El trait recibe un array pre-cargado de categorías en lugar de consultar la base de datos en cada iteración (optimización).
Importación de Productos
Uso: Asignación automática de categoría IVA durante importación masiva.
Método usado: getByPorcentaje(float $porcentaje)
Contexto: Al importar productos desde archivo Excel/CSV, se busca la categoría por porcentaje.
Servicios Externos
ARCA (AFIP) - Webservice WSFE
Integración: Los códigos de la tabla aliva corresponden a la codificación oficial de ARCA para facturación electrónica.
Uso: Al emitir un comprobante electrónico, se envían las alícuotas de IVA con sus códigos oficiales.
Ejemplo de request ARCA:
php
'IvaAliq' => [
[
'Id' => 5, // Código de aliva
'BaseImp' => 1000.00,
'Importe' => 210.00
]
]Normativa: RG 5616/2024 ARCA - Códigos de alícuota de IVA.
Estrategia de Testing
Unit Tests
NO IMPLEMENTADOS - No se encontraron tests unitarios para este módulo.
Tests recomendados (si se implementaran):
php
// CategoriaIvaModelTest.php
class CategoriaIvaModelTest extends TestCase
{
public function testGetAllReturnsArray(): void;
public function testGetByCodigoReturnsDTO(): void;
public function testGetByCodigoReturnsNullWhenNotFound(): void;
public function testGetByPorcentajeReturnsDTO(): void;
public function testGetByPorcentajeReturnsNullWhenNotFound(): void;
}Integration Tests
NO IMPLEMENTADOS - No se encontraron tests de integración.
Tests recomendados (si se implementaran):
php
// CategoriaIvaIntegrationTest.php
class CategoriaIvaIntegrationTest extends BaseIntegrationTestCase
{
public function testEndpointReturnsAllCategories(): void;
public function testEndpointReturnsOneByCode(): void;
public function testEndpointReturnsOneByPercentage(): void;
public function testEndpointReturns404WhenNotFound(): void;
}Mocking Strategy
Para tests que usan CategoriaIva como dependencia (ej: tests de facturación):
Mock de Model:
php
$mockCategoriaIvaModel = $this->createMock(CategoriaIva::class);
$mockCategoriaIvaModel->method('getByCodigo')
->willReturn(new CategoriaIvaDTO(5, 21.00, 'IVA 21 %'));Mock de DTO:
php
$categoriaIva = new CategoriaIvaDTO(
codigo: 5,
porcentaje: 21.00,
nombre: 'IVA 21 %'
);Rendimiento
Volumen de Datos
- Registros actuales: 6 (datos de referencia fiscal)
- Crecimiento esperado: Muy bajo (solo cuando cambia normativa ARCA)
- Paginación: NO requerida
Optimizaciones Implementadas
Consultas
- Queries simples sin JOINs
- PRIMARY KEY en
codigo(acceso O(1)) - No se requieren índices adicionales
Caching
NO IMPLEMENTADO - No se encontró cache de categorías.
Recomendación: Dado que los datos son estables y de bajo volumen, se podría implementar cache en memoria:
php
// Cache sugerido (no implementado)
private static ?array $categoriesCache = null;
public function getAll(): array
{
if (self::$categoriesCache === null) {
self::$categoriesCache = // query DB
}
return self::$categoriesCache;
}Justificación: Las categorías de IVA cambian raramente (solo con cambios legislativos) y se consultan frecuentemente en procesos de facturación.
Seguridad
Autenticación
- JWT requerido: Implementado en
JwtHandler.php(include en route legacy) - Validación: Token debe ser válido con firma RSA
- Payload: Contiene
db,schema,id,permisos
Autorización
NO IMPLEMENTADA - No hay validación de permisos específica.
Comportamiento actual: Cualquier usuario autenticado puede consultar categorías de IVA.
Justificación: Los datos son públicos (normativa fiscal) y no contienen información sensible.
Sanitización
Prevención de SQL Injection:
- ✅ Uso de prepared statements en todos los métodos del Model
- ✅ PDO con placeholders (
:codigo,:porcentaje)
Ejemplo:
php
$stmt->execute([':codigo' => $codigo]);Auditoría
NO IMPLEMENTADA - No se registran operaciones de auditoría.
Justificación: Recurso de solo lectura. Los cambios a los datos se realizan exclusivamente vía migraciones controladas por desarrollo.
Preguntas Técnicas Pendientes
⚠️ Aclaraciones Requeridas: Hay aspectos técnicos que requieren validación.
Ver: Preguntas sobre Categoria IVA
Preguntas técnicas principales:
- Migración a Slim Routes: ¿Se planea migrar el endpoint legacy a Slim Framework con Validator middleware?
- Cache: ¿Se debería implementar cache dado el bajo volumen y alta estabilidad de datos?
- Tests: ¿Se requiere cobertura de tests para este módulo?
- Validator: ¿Se necesita validación estructural con middleware antes del DTO?
Referencias
Notas Adicionales
Legacy vs Modern Architecture
Este módulo utiliza arquitectura legacy (route manual en backend/categoria-iva.php) en lugar del patrón moderno Slim Framework.
Patrón moderno esperado (no implementado):
php
// Routes/Venta/CategoriaIvaRoutes.php (NO EXISTE)
$group->get('/categoria-iva', [CategoriaIvaController::class, 'getAll']);
$group->get('/categoria-iva/{codigo}', [CategoriaIvaController::class, 'getById']);Implicación: El endpoint actual no se beneficia de middleware de validación, CORS mejorado, ni inyección de dependencias de Slim.
Normativa Fiscal
Los códigos de alícuota deben mantenerse sincronizados con la normativa de ARCA:
- Fuente oficial: Resolución General 5616/2024 ARCA
- Cambios: Solo mediante migraciones aprobadas por desarrollo
- Verificación: Antes de migración, validar contra webservice ARCA homologación
⚠️ NOTA IMPORTANTE: Esta documentación fue generada automáticamente analizando el código implementado. Validar cambios futuros contra este baseline. Las categorías de IVA son datos fiscales regulados que solo se modifican mediante migraciones controladas cuando cambia la normativa de ARCA.