# US-MGN-004-004-001: CRUD de Impuestos

**RF Asociado:** [RF-MGN-004-004](../../02-modelado/requerimientos-funcionales/mgn-004/RF-MGN-004-004-gestión-de-impuestos.md)
**Módulo:** MGN-004 - Financiero Básico
**Epic:** Impuestos
**Prioridad:** P0 (MVP)
**Story Points:** 5
**Sprint:** Sprint 9
**Estado:** Ready for Development
**Fecha:** 2025-11-24

---

## User Story

**Como** contador,
**Quiero** crear y gestionar impuestos (IVA, retenciones, etc.),
**Para** calcular automáticamente los impuestos en facturas y generar reportes fiscales.

---

## Descripción Detallada

Los impuestos son configuraciones que definen cómo calcular impuestos sobre transacciones. Cada impuesto tiene:
- Código y nombre (ej: "IVA 21%")
- Tipo: sale (ventas), purchase (compras), both (ambos)
- Método de cálculo: percentage (porcentaje) o fixed (monto fijo)
- Rate (tasa): 0-100 para percentage, monto para fixed
- Cuentas contables asociadas (tax_collected_account, tax_paid_account)
- Grupo de impuestos (opcional, para impuestos compuestos)

---

## Criterios de Aceptación

### Escenario 1: Crear impuesto porcentual exitosamente
**Dado que** soy contador con permisos accounting_manager,
**Cuando** creo un impuesto con code="IVA21", name="IVA 21%", type="both", rate=21.0, method="percentage",
**Entonces** el sistema crea el impuesto y retorna el registro con id y company_id.

### Escenario 2: Validar rate entre 0 y 100
**Dado que** intento crear un impuesto con rate=150,
**Cuando** envío el request,
**Entonces** el sistema retorna error 400 "Rate debe estar entre 0 y 100".

### Escenario 3: Listar impuestos con filtro por tipo
**Dado que** tengo impuestos de tipo sale y purchase,
**Cuando** listo impuestos con filtro type="sale",
**Entonces** el sistema retorna solo impuestos aplicables a ventas (type='sale' o type='both').

### Escenario 4: Calcular monto de impuesto
**Dado que** tengo un impuesto con rate=21%,
**Cuando** calculo el impuesto sobre base=1000,
**Entonces** el sistema retorna tax_amount=210.

### Escenario 5: Validar cuenta contable existe
**Dado que** intento crear un impuesto con tax_collected_account_id=999 (no existe),
**Cuando** envío el request,
**Entonces** el sistema retorna error 400 "Cuenta contable no encontrada".

---

## Reglas de Negocio

- **RN-1:** Code debe ser único por empresa.
- **RN-2:** Tipos válidos: sale, purchase, both.
- **RN-3:** Métodos válidos: percentage, fixed.
- **RN-4:** Rate debe estar entre 0 y 100 para percentage.
- **RN-5:** tax_collected_account_id es obligatorio para type='sale' o 'both'.
- **RN-6:** tax_paid_account_id es obligatorio para type='purchase' o 'both'.
- **RN-7:** Impuestos pueden estar activos o inactivos.
- **RN-8:** RLS filtra por company_id.

---

## Tareas Técnicas

### Backend
- [ ] Endpoint: `POST /api/v1/financial/taxes`
- [ ] Endpoint: `GET /api/v1/financial/taxes` (filtros: type, active)
- [ ] Endpoint: `GET /api/v1/financial/taxes/:id`
- [ ] Endpoint: `PUT /api/v1/financial/taxes/:id`
- [ ] Endpoint: `DELETE /api/v1/financial/taxes/:id` (soft delete)
- [ ] Endpoint: `POST /api/v1/financial/taxes/calculate` (calcular impuesto)
- [ ] Service: `TaxService.create/findAll/findOne/update/remove/calculateTax`
- [ ] DTO: `CreateTaxDto` (validaciones @Min(0) @Max(100) para rate)
- [ ] DTO: `CalculateTaxDto` (tax_id, base_amount)
- [ ] Unit tests (10 test cases)
- [ ] Integration tests (8 test cases)

### Frontend
- [ ] Página: `TaxesPage.tsx` (/financial/taxes)
- [ ] Componente: `TaxesTable.tsx`
- [ ] Componente: `CreateTaxForm.tsx`
- [ ] API client: `taxApi.ts`
- [ ] Store: `useTaxStore.ts`
- [ ] Component tests (5 test cases)
- [ ] E2E test: "should create tax successfully"

### Database
- [ ] Tabla: `financial.taxes` (ya existe)
- [ ] Índices: idx_taxes_company_id, idx_taxes_type, idx_taxes_code
- [ ] Constraint: uq_taxes_code_company
- [ ] RLS policy: company_isolation_taxes

---

## Mockups / Wireframes

**Formulario Crear Impuesto:**
```
┌───────────────────────────────────────┐
│ Código: [IVA21__] (required)         │
│ Nombre: [IVA 21%__] (required)       │
│ Tipo: [Ambos ▼] (Sale/Purchase/Both) │
│ Método: [Porcentaje ▼] (%)           │
│ Tasa: [21___] %                       │
│ Cuenta Impuesto Cobrado: [Select ▼]  │
│ Cuenta Impuesto Pagado: [Select ▼]   │
│ Activo: [✓]                           │
│ [Guardar] [Cancelar]                  │
└───────────────────────────────────────┘
```

---

## Casos de Prueba

### Funcionales
1. **TC-001:** Crear impuesto percentage exitosamente
2. **TC-002:** Crear impuesto fixed exitosamente
3. **TC-003:** Error por rate > 100
4. **TC-004:** Error por código duplicado
5. **TC-005:** Listar impuestos con filtro type
6. **TC-006:** Calcular impuesto 21% sobre 1000 = 210
7. **TC-007:** Validar cuenta contable existe
8. **TC-008:** RLS filtra por empresa

### No Funcionales
1. **Performance:** < 200ms
2. **Seguridad:** JWT + accounting_manager

---

## Dependencias

- **US bloqueantes:**
  - US-MGN-004-001-001 (CRUD Cuentas) - Para tax_collected_account_id
  - US-MGN-002-001-001 (CRUD Empresas)
- **Módulos:** MGN-002, MGN-004

---

## Estimación Detallada

| Tarea | Estimación |
|-------|------------|
| Backend | 3 horas |
| Frontend | 3 horas |
| Testing | 2 horas |
| Code Review | 1 hora |
| **TOTAL** | **9 horas = 5 SP** |

---

## Definition of Done

- [ ] Código implementado
- [ ] Tests pasando (>80%)
- [ ] Code review aprobado
- [ ] Swagger docs actualizado
- [ ] RLS aplicado
- [ ] Merge a develop
- [ ] QA validado
- [ ] PO aprobado

---

## Referencias

- [RF-MGN-004-004](../../02-modelado/requerimientos-funcionales/mgn-004/RF-MGN-004-004-gestión-de-impuestos.md)
- [ET-BACKEND-MGN-004-004](../../02-modelado/especificaciones-tecnicas/backend/mgn-004/ET-BACKEND-MGN-004-004-gestión-de-impuestos.md)
- [ET-FRONTEND-MGN-004-004](../../02-modelado/especificaciones-tecnicas/frontend/mgn-004/ET-FRONTEND-MGN-004-004-gestión-de-impuestos.md)
- [TRACEABILITY-MGN-004.yaml](../../02-modelado/trazabilidad/TRACEABILITY-MGN-004.yaml)
- [Financial Schema DDL](../../02-modelado/database-design/schemas/financial-schema-ddl.sql)
