# Documentacion de Modulos Backend

Este documento detalla la implementacion de cada modulo del backend.

---

## Indice

1. [Auth Module](#auth-module)
2. [Budgets Module (MAI-003)](#budgets-module-mai-003)
3. [Progress Module (MAI-005)](#progress-module-mai-005)
4. [Estimates Module (MAI-008)](#estimates-module-mai-008)
5. [Construction Module (MAI-002)](#construction-module-mai-002)
6. [HR Module (MAI-007)](#hr-module-mai-007)
7. [HSE Module (MAA-017)](#hse-module-maa-017)
8. [Core Module](#core-module)

---

## Auth Module

**Ubicacion:** `backend/src/modules/auth/`

### Descripcion

Modulo de autenticacion JWT con refresh tokens y soporte multi-tenant.

### Estructura

```
auth/
├── dto/
│   └── auth.dto.ts          # DTOs de autenticacion
├── services/
│   └── auth.service.ts      # Logica de autenticacion
├── middleware/
│   └── auth.middleware.ts   # Middleware JWT
└── index.ts                 # Exports
```

### DTOs

```typescript
// LoginDto
{
  email: string;      // Email del usuario
  password: string;   // Password
}

// RegisterDto
{
  email: string;
  password: string;
  firstName: string;
  lastName: string;
  tenantId: string;   // Tenant al que pertenece
}

// RefreshTokenDto
{
  refreshToken: string;
}

// AuthResponse
{
  user: UserDto;
  accessToken: string;
  refreshToken: string;
  expiresIn: number;
}
```

### AuthService

| Metodo | Descripcion | Parametros | Retorna |
|--------|-------------|------------|---------|
| `login` | Autentica usuario | `LoginDto` | `AuthResponse` |
| `register` | Registra nuevo usuario | `RegisterDto` | `AuthResponse` |
| `refresh` | Renueva tokens | `RefreshTokenDto` | `AuthResponse` |
| `logout` | Revoca refresh token | `token: string` | `boolean` |
| `changePassword` | Cambia password | `ChangePasswordDto` | `boolean` |
| `validateToken` | Valida JWT | `token: string` | `JwtPayload` |

### AuthMiddleware

| Metodo | Descripcion |
|--------|-------------|
| `authenticate` | Valida JWT (requerido) |
| `optionalAuthenticate` | Valida JWT (opcional) |
| `authorize(...roles)` | Autoriza por roles |
| `requireAdmin` | Solo admin/super_admin |
| `requireSupervisor` | Solo supervisores+ |
| `setRLSContext` | Configura tenant en sesion PostgreSQL |

### Ejemplo de Uso

```typescript
// Login
const auth = await authService.login({
  email: 'user@example.com',
  password: 'securePassword123'
});

// Usar token en requests
headers: {
  'Authorization': `Bearer ${auth.accessToken}`
}

// Refresh cuando expire
const newAuth = await authService.refresh({
  refreshToken: auth.refreshToken
});
```

---

## Budgets Module (MAI-003)

**Ubicacion:** `backend/src/modules/budgets/`

### Descripcion

Gestion de catalogos de conceptos y presupuestos de obra.

### Estructura

```
budgets/
├── entities/
│   ├── concepto.entity.ts
│   ├── presupuesto.entity.ts
│   └── presupuesto-partida.entity.ts
├── services/
│   ├── concepto.service.ts
│   └── presupuesto.service.ts
└── index.ts
```

### Entidades

#### Concepto

Catalogo jerarquico de conceptos de obra.

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `tenantId` | UUID | Discriminador multi-tenant |
| `code` | string | Codigo unico (ej: "01.02.003") |
| `name` | string | Nombre del concepto |
| `description` | string | Descripcion detallada |
| `unit` | string | Unidad de medida (M2, ML, PZA) |
| `unitPrice` | decimal | Precio unitario |
| `parentId` | UUID | Concepto padre (null=raiz) |
| `level` | number | Nivel jerarquico (0=raiz) |
| `path` | string | Ruta completa (ej: "01/02/003") |
| `isActive` | boolean | Activo para uso |

**Relaciones:**
- `parent` → Concepto (auto-referencial)
- `children` → Concepto[] (hijos)

#### Presupuesto

Presupuesto versionado de obra.

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `tenantId` | UUID | Discriminador |
| `fraccionamientoId` | UUID | Proyecto asociado |
| `code` | string | Codigo del presupuesto |
| `name` | string | Nombre descriptivo |
| `version` | number | Version (1, 2, 3...) |
| `status` | enum | draft/submitted/approved |
| `totalAmount` | decimal | Total calculado |
| `approvedAt` | timestamp | Fecha de aprobacion |
| `approvedById` | UUID | Usuario que aprobo |

**Relaciones:**
- `fraccionamiento` → Fraccionamiento
- `partidas` → PresupuestoPartida[]

#### PresupuestoPartida

Lineas de presupuesto.

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `presupuestoId` | UUID | Presupuesto padre |
| `conceptoId` | UUID | Concepto referenciado |
| `quantity` | decimal | Cantidad |
| `unitPrice` | decimal | Precio unitario |
| `totalAmount` | decimal | **GENERADO**: quantity * unitPrice |

### ConceptoService

| Metodo | Descripcion |
|--------|-------------|
| `createConcepto(ctx, dto)` | Crea concepto, calcula nivel/path |
| `findRootConceptos(ctx)` | Conceptos raiz (nivel 0) |
| `findChildren(ctx, parentId)` | Hijos de un concepto |
| `getConceptoTree(ctx, rootId?)` | Arbol completo/parcial |
| `search(ctx, term)` | Busqueda por codigo/nombre |

### PresupuestoService

| Metodo | Descripcion |
|--------|-------------|
| `createPresupuesto(ctx, dto)` | Crea presupuesto |
| `findByFraccionamiento(ctx, id)` | Por proyecto |
| `findWithPartidas(ctx, id)` | Con lineas cargadas |
| `addPartida(ctx, presupuestoId, dto)` | Agregar linea |
| `updatePartida(ctx, partidaId, dto)` | Modificar linea |
| `removePartida(ctx, partidaId)` | Eliminar linea |
| `recalculateTotal(ctx, presupuestoId)` | Recalcular total |
| `createNewVersion(ctx, presupuestoId)` | Crear version nueva |
| `approve(ctx, presupuestoId)` | Aprobar presupuesto |

---

## Progress Module (MAI-005)

**Ubicacion:** `backend/src/modules/progress/`

### Descripcion

Control de avances fisicos, bitacora y programacion de obra.

### Estructura

```
progress/
├── entities/
│   ├── avance-obra.entity.ts
│   ├── foto-avance.entity.ts
│   ├── bitacora-obra.entity.ts
│   ├── programa-obra.entity.ts
│   └── programa-actividad.entity.ts
├── services/
│   ├── avance-obra.service.ts
│   └── bitacora-obra.service.ts
└── index.ts
```

### Entidades

#### AvanceObra

Registro de avance fisico con workflow.

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `tenantId` | UUID | Discriminador |
| `loteId` | UUID | Lote donde se registro |
| `departamentoId` | UUID | Departamento (opcional) |
| `conceptoId` | UUID | Concepto de catalogo |
| `quantity` | decimal | Cantidad ejecutada |
| `progressDate` | date | Fecha de avance |
| `status` | enum | captured/reviewed/approved/rejected |
| `capturedById` | UUID | Usuario que capturo |
| `reviewedAt` | timestamp | Fecha de revision |
| `approvedAt` | timestamp | Fecha de aprobacion |
| `rejectionReason` | string | Motivo de rechazo |
| `notes` | string | Notas adicionales |

#### FotoAvance

Evidencia fotografica con geolocalización.

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `avanceObraId` | UUID | Avance asociado |
| `fileName` | string | Nombre del archivo |
| `filePath` | string | Ruta en storage |
| `fileSize` | number | Tamano en bytes |
| `mimeType` | string | Tipo MIME |
| `latitude` | decimal | Latitud GPS |
| `longitude` | decimal | Longitud GPS |
| `takenAt` | timestamp | Fecha de captura |
| `description` | string | Descripcion |

#### BitacoraObra

Bitacora diaria de obra.

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `tenantId` | UUID | Discriminador |
| `fraccionamientoId` | UUID | Proyecto |
| `entryNumber` | number | Numero secuencial |
| `entryDate` | date | Fecha de entrada |
| `weather` | string | Clima del dia |
| `temperature` | decimal | Temperatura |
| `workersCount` | number | Personal en obra |
| `activities` | text | Actividades realizadas |
| `incidents` | text | Incidentes |
| `observations` | text | Observaciones |
| `createdById` | UUID | Usuario que creo |

### AvanceObraService

| Metodo | Descripcion |
|--------|-------------|
| `createAvance(ctx, dto)` | Crear avance en status captured |
| `findByLote(ctx, loteId)` | Avances de un lote |
| `findByDepartamento(ctx, deptoId)` | Avances de departamento |
| `findWithFilters(ctx, filters)` | Busqueda con filtros |
| `findWithFotos(ctx, id)` | Avance con fotos |
| `addFoto(ctx, avanceId, dto)` | Agregar foto |
| `review(ctx, id)` | Workflow: revisar |
| `approve(ctx, id)` | Workflow: aprobar |
| `reject(ctx, id, reason)` | Workflow: rechazar |
| `getAccumulatedProgress(ctx)` | Acumulado por concepto |

### BitacoraObraService

| Metodo | Descripcion |
|--------|-------------|
| `createEntry(ctx, dto)` | Crear entrada (numero automatico) |
| `findByFraccionamiento(ctx, id)` | Entradas de proyecto |
| `findWithFilters(ctx, id, filters)` | Con filtros |
| `findByDate(ctx, id, date)` | Por fecha especifica |
| `findLatest(ctx, id)` | Ultima entrada |
| `getStats(ctx, id)` | Estadisticas |

---

## Estimates Module (MAI-008)

**Ubicacion:** `backend/src/modules/estimates/`

### Descripcion

Estimaciones periodicas con workflow de aprobacion completo.

### Estructura

```
estimates/
├── entities/
│   ├── estimacion.entity.ts
│   ├── estimacion-concepto.entity.ts
│   ├── generador.entity.ts
│   ├── anticipo.entity.ts
│   ├── amortizacion.entity.ts
│   ├── retencion.entity.ts
│   ├── fondo-garantia.entity.ts
│   └── estimacion-workflow.entity.ts
├── services/
│   └── estimacion.service.ts
└── index.ts
```

### Entidades

#### Estimacion

Estimacion periodica principal.

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `tenantId` | UUID | Discriminador |
| `contratoId` | UUID | Contrato asociado |
| `number` | number | Numero secuencial |
| `periodStart` | date | Inicio del periodo |
| `periodEnd` | date | Fin del periodo |
| `status` | enum | draft/submitted/reviewed/approved/rejected |
| `subtotal` | decimal | Suma de conceptos |
| `iva` | decimal | IVA calculado |
| `retentions` | decimal | Retenciones |
| `amortization` | decimal | Amortizacion de anticipo |
| `totalAmount` | decimal | Total neto |
| `submittedAt` | timestamp | Fecha de envio |
| `reviewedAt` | timestamp | Fecha de revision |
| `approvedAt` | timestamp | Fecha de aprobacion |
| `rejectionReason` | string | Motivo de rechazo |

#### EstimacionConcepto

Lineas de estimacion con acumulados.

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `estimacionId` | UUID | Estimacion padre |
| `conceptoId` | UUID | Concepto de catalogo |
| `contractQuantity` | decimal | Cantidad contratada |
| `previousQuantity` | decimal | Cantidad acumulada anterior |
| `currentQuantity` | decimal | Cantidad este periodo |
| `accumulatedQuantity` | decimal | **GENERADO**: previous + current |
| `pendingQuantity` | decimal | **GENERADO**: contract - accumulated |
| `unitPrice` | decimal | Precio unitario |
| `currentAmount` | decimal | **GENERADO**: current * price |
| `accumulatedAmount` | decimal | **GENERADO**: accumulated * price |

#### Generador

Numeros generadores (desglose de cantidades).

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `estimacionConceptoId` | UUID | Linea de estimacion |
| `description` | string | Descripcion del calculo |
| `length` | decimal | Largo |
| `width` | decimal | Ancho |
| `height` | decimal | Alto |
| `quantity` | decimal | Cantidad/Piezas |
| `partial` | decimal | **GENERADO**: formula |
| `formula` | string | Formula aplicada |

#### Anticipo

Anticipos de contrato.

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `contratoId` | UUID | Contrato |
| `type` | enum | obra/materiales |
| `percentage` | decimal | Porcentaje del contrato |
| `amount` | decimal | Monto del anticipo |
| `grantedDate` | date | Fecha de otorgamiento |
| `amortizedAmount` | decimal | Monto ya amortizado |
| `pendingAmount` | decimal | **GENERADO** |
| `status` | enum | pending/partial/completed |

#### FondoGarantia

Fondo de garantia acumulado.

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `contratoId` | UUID | Contrato |
| `percentage` | decimal | Porcentaje retenido |
| `accumulatedAmount` | decimal | Monto acumulado |
| `releasedAmount` | decimal | Monto liberado |
| `pendingAmount` | decimal | **GENERADO** |

### EstimacionService

| Metodo | Descripcion |
|--------|-------------|
| `createEstimacion(ctx, dto)` | Crear con numero automatico |
| `findByContrato(ctx, contratoId)` | Estimaciones de contrato |
| `findWithFilters(ctx, filters)` | Busqueda con filtros |
| `findWithDetails(ctx, id)` | Con todas las relaciones |
| `addConcepto(ctx, estimacionId, dto)` | Agregar linea |
| `addGenerador(ctx, conceptoId, dto)` | Agregar generador |
| `recalculateTotals(ctx, id)` | Recalcular totales |
| `submit(ctx, id)` | Workflow: enviar |
| `review(ctx, id)` | Workflow: revisar |
| `approve(ctx, id)` | Workflow: aprobar |
| `reject(ctx, id, reason)` | Workflow: rechazar |
| `getContractSummary(ctx, contratoId)` | Resumen financiero |

---

## Construction Module (MAI-002)

**Ubicacion:** `backend/src/modules/construction/`

### Descripcion

Gestion de proyectos y estructura organizacional.

### Entidades

#### Proyecto

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `tenantId` | UUID | Discriminador |
| `code` | string | Codigo del proyecto |
| `name` | string | Nombre |
| `description` | text | Descripcion |
| `status` | enum | planning/in_progress/completed/cancelled |
| `startDate` | date | Fecha inicio |
| `endDate` | date | Fecha fin |
| `budget` | decimal | Presupuesto total |
| `location` | geography | Ubicacion GPS |
| `address` | string | Direccion |
| `city` | string | Ciudad |
| `state` | string | Estado |

#### Fraccionamiento

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `tenantId` | UUID | Discriminador |
| `proyectoId` | UUID | Proyecto padre |
| `code` | string | Codigo |
| `name` | string | Nombre |
| `totalLots` | number | Total de lotes |
| `builtLots` | number | Lotes construidos |
| `soldLots` | number | Lotes vendidos |

---

## HR Module (MAI-007)

**Ubicacion:** `backend/src/modules/hr/`

### Descripcion

Gestion de recursos humanos y asignaciones.

### Entidades

#### Employee

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `tenantId` | UUID | Discriminador |
| `employeeNumber` | string | Numero de empleado |
| `firstName` | string | Nombre |
| `lastName` | string | Apellidos |
| `email` | string | Email |
| `phone` | string | Telefono |
| `hireDate` | date | Fecha de contratacion |
| `puestoId` | UUID | Puesto |
| `status` | enum | active/inactive/terminated |
| `dailyRate` | decimal | Salario diario |
| `imssNumber` | string | Numero IMSS |
| `curp` | string | CURP |
| `rfc` | string | RFC |

#### Puesto

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `tenantId` | UUID | Discriminador |
| `code` | string | Codigo |
| `name` | string | Nombre del puesto |
| `department` | string | Departamento |
| `level` | number | Nivel jerarquico |
| `baseSalary` | decimal | Salario base |

#### EmployeeFraccionamiento

Asignacion de empleados a proyectos.

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `employeeId` | UUID | Empleado |
| `fraccionamientoId` | UUID | Proyecto |
| `role` | string | Rol en el proyecto |
| `startDate` | date | Fecha inicio |
| `endDate` | date | Fecha fin (null=activo) |

---

## HSE Module (MAA-017)

**Ubicacion:** `backend/src/modules/hse/`

### Descripcion

Seguridad, salud y medio ambiente.

### Entidades

#### Incidente

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `tenantId` | UUID | Discriminador |
| `fraccionamientoId` | UUID | Proyecto |
| `incidentNumber` | string | Numero de reporte |
| `incidentDate` | timestamp | Fecha y hora |
| `type` | enum | accident/near_miss/incident |
| `severity` | enum | low/medium/high/critical |
| `description` | text | Descripcion |
| `location` | string | Ubicacion |
| `immediateActions` | text | Acciones inmediatas |
| `rootCause` | text | Causa raiz |
| `status` | enum | reported/investigating/closed |
| `reportedById` | UUID | Quien reporto |

#### IncidenteInvolucrado

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `incidenteId` | UUID | Incidente |
| `employeeId` | UUID | Empleado (opcional) |
| `name` | string | Nombre (si no es empleado) |
| `role` | enum | victim/witness/reporter |
| `injuryType` | string | Tipo de lesion |
| `treatmentRequired` | boolean | Requirio tratamiento |

#### IncidenteAccion

Acciones correctivas.

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `incidenteId` | UUID | Incidente |
| `description` | text | Descripcion de la accion |
| `responsibleId` | UUID | Responsable |
| `dueDate` | date | Fecha limite |
| `completedAt` | timestamp | Fecha de cierre |
| `status` | enum | pending/in_progress/completed |

#### Capacitacion

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `tenantId` | UUID | Discriminador |
| `name` | string | Nombre del curso |
| `type` | enum | induction/specific/recertification |
| `duration` | number | Duracion en horas |
| `validityMonths` | number | Vigencia en meses |
| `instructor` | string | Instructor |
| `scheduledDate` | date | Fecha programada |
| `status` | enum | scheduled/completed/cancelled |

---

## Core Module

**Ubicacion:** `backend/src/modules/core/`

### Descripcion

Entidades base del sistema (usuarios, tenants).

### Entidades

#### User

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `email` | string | Email unico |
| `passwordHash` | string | Password hasheado |
| `firstName` | string | Nombre |
| `lastName` | string | Apellidos |
| `role` | enum | Rol del sistema |
| `isActive` | boolean | Usuario activo |
| `lastLoginAt` | timestamp | Ultimo acceso |
| `emailVerifiedAt` | timestamp | Email verificado |

#### Tenant

| Campo | Tipo | Descripcion |
|-------|------|-------------|
| `id` | UUID | Primary key |
| `code` | string | Codigo unico |
| `name` | string | Nombre de la empresa |
| `subdomain` | string | Subdominio |
| `plan` | enum | basic/professional/enterprise |
| `isActive` | boolean | Tenant activo |
| `settings` | jsonb | Configuraciones |
| `createdAt` | timestamp | Fecha de creacion |

---

## Shared: BaseService

**Ubicacion:** `backend/src/shared/services/base.service.ts`

### Descripcion

Servicio base abstracto que proporciona operaciones CRUD multi-tenant.

### Interface ServiceContext

```typescript
interface ServiceContext {
  tenantId: string;
  userId: string;
}
```

### Interface PaginatedResult

```typescript
interface PaginatedResult<T> {
  data: T[];
  total: number;
  page: number;
  limit: number;
  totalPages: number;
}
```

### Metodos

| Metodo | Descripcion | Retorna |
|--------|-------------|---------|
| `findAll(ctx, options?)` | Listado paginado | `PaginatedResult<T>` |
| `findById(ctx, id)` | Por ID | `T \| null` |
| `findOne(ctx, where)` | Por condicion | `T \| null` |
| `find(ctx, options)` | Por opciones | `T[]` |
| `create(ctx, data)` | Crear registro | `T` |
| `update(ctx, id, data)` | Actualizar | `T \| null` |
| `softDelete(ctx, id)` | Borrado logico | `boolean` |
| `hardDelete(ctx, id)` | Borrado fisico | `boolean` |
| `count(ctx, where?)` | Contar registros | `number` |
| `exists(ctx, where)` | Verificar existencia | `boolean` |

### Ejemplo de Uso

```typescript
class MiService extends BaseService<MiEntity> {
  constructor(repository: Repository<MiEntity>) {
    super(repository);
  }

  // Metodos personalizados
  async findActive(ctx: ServiceContext): Promise<MiEntity[]> {
    return this.find(ctx, {
      where: { isActive: true },
      order: { createdAt: 'DESC' },
    });
  }
}

// Uso
const ctx = { tenantId: 'uuid', userId: 'uuid' };
const items = await miService.findAll(ctx, { page: 1, limit: 10 });
const item = await miService.findById(ctx, 'item-uuid');
const created = await miService.create(ctx, { name: 'Nuevo' });
```

---

**Ultima actualizacion:** 2025-12-12
