# Backend - ERP Construccion

API REST para sistema de administracion de obra e INFONAVIT.

| Campo | Valor |
|-------|-------|
| **Stack** | Node.js 20 + Express 4 + TypeScript 5 + TypeORM 0.3 |
| **Version** | 1.0.0 |
| **Entidades** | 30 |
| **Services** | 8 |
| **Arquitectura** | Multi-tenant con RLS |

---

## Quick Start

```bash
# Instalar dependencias
npm install

# Configurar variables de entorno
cp ../.env.example .env

# Desarrollo con hot-reload
npm run dev

# El servidor estara en http://localhost:3000
```

---

## Estructura del Proyecto

```
src/
├── modules/
│   ├── auth/                    # Autenticacion JWT
│   │   ├── dto/
│   │   │   └── auth.dto.ts      # DTOs tipados
│   │   ├── middleware/
│   │   │   └── auth.middleware.ts
│   │   ├── services/
│   │   │   └── auth.service.ts
│   │   └── index.ts
│   │
│   ├── budgets/                 # MAI-003 Presupuestos
│   │   ├── entities/
│   │   │   ├── concepto.entity.ts
│   │   │   ├── presupuesto.entity.ts
│   │   │   └── presupuesto-partida.entity.ts
│   │   ├── services/
│   │   │   ├── concepto.service.ts
│   │   │   └── presupuesto.service.ts
│   │   └── index.ts
│   │
│   ├── progress/                # MAI-005 Control de Obra
│   │   ├── 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
│   │
│   ├── estimates/               # MAI-008 Estimaciones
│   │   ├── 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
│   │
│   ├── construction/            # MAI-002 Proyectos
│   │   └── entities/
│   │       ├── proyecto.entity.ts
│   │       └── fraccionamiento.entity.ts
│   │
│   ├── hr/                      # MAI-007 RRHH
│   │   └── entities/
│   │       ├── employee.entity.ts
│   │       ├── puesto.entity.ts
│   │       └── employee-fraccionamiento.entity.ts
│   │
│   ├── hse/                     # MAA-017 Seguridad HSE
│   │   └── entities/
│   │       ├── incidente.entity.ts
│   │       ├── incidente-involucrado.entity.ts
│   │       ├── incidente-accion.entity.ts
│   │       └── capacitacion.entity.ts
│   │
│   └── core/                    # Entidades base
│       └── entities/
│           ├── user.entity.ts
│           └── tenant.entity.ts
│
└── shared/
    ├── constants/               # SSOT
    │   ├── database.constants.ts
    │   ├── api.constants.ts
    │   ├── enums.constants.ts
    │   └── index.ts
    ├── services/
    │   └── base.service.ts      # CRUD multi-tenant
    └── database/
        └── typeorm.config.ts
```

---

## Modulos Implementados

### Auth Module

Autenticacion JWT con refresh tokens y multi-tenancy.

```typescript
// Services
AuthService
  ├── login(dto)          // Login con email/password
  ├── register(dto)       // Registro de usuarios
  ├── refresh(dto)        // Renovar tokens
  ├── logout(token)       // Revocar refresh token
  └── changePassword(dto) // Cambiar password

// Middleware
AuthMiddleware
  ├── authenticate        // Validar JWT (requerido)
  ├── optionalAuthenticate // Validar JWT (opcional)
  ├── authorize(...roles) // Autorizar por roles
  ├── requireAdmin        // Solo admin/super_admin
  └── requireSupervisor   // Solo supervisores+
```

### Budgets Module (MAI-003)

Catalogo de conceptos y presupuestos de obra.

```typescript
// Entities
Concepto           // Catalogo jerarquico (arbol)
Presupuesto        // Presupuestos versionados
PresupuestoPartida // Lineas con calculo automatico

// Services
ConceptoService
  ├── createConcepto(ctx, dto)     // Crear con nivel/path automatico
  ├── findRootConceptos(ctx)       // Conceptos raiz
  ├── findChildren(ctx, parentId)  // Hijos de un concepto
  ├── getConceptoTree(ctx, rootId) // Arbol completo
  └── search(ctx, term)            // Busqueda por codigo/nombre

PresupuestoService
  ├── createPresupuesto(ctx, dto)
  ├── findByFraccionamiento(ctx, id)
  ├── findWithPartidas(ctx, id)
  ├── addPartida(ctx, id, dto)
  ├── updatePartida(ctx, id, dto)
  ├── removePartida(ctx, id)
  ├── recalculateTotal(ctx, id)
  ├── createNewVersion(ctx, id)    // Versionamiento
  └── approve(ctx, id)
```

### Progress Module (MAI-005)

Control de avances fisicos y bitacora de obra.

```typescript
// Entities
AvanceObra         // Avances con workflow
FotoAvance         // Evidencias fotograficas con GPS
BitacoraObra       // Bitacora diaria
ProgramaObra       // Programa maestro
ProgramaActividad  // Actividades WBS

// Services
AvanceObraService
  ├── createAvance(ctx, dto)
  ├── findByLote(ctx, loteId)
  ├── findByDepartamento(ctx, deptoId)
  ├── findWithFilters(ctx, filters)
  ├── findWithFotos(ctx, id)
  ├── addFoto(ctx, id, dto)
  ├── review(ctx, id)              // Workflow: revisar
  ├── approve(ctx, id)             // Workflow: aprobar
  ├── reject(ctx, id, reason)      // Workflow: rechazar
  └── getAccumulatedProgress(ctx)  // Acumulado por concepto

BitacoraObraService
  ├── createEntry(ctx, dto)        // Numero automatico
  ├── findByFraccionamiento(ctx, id)
  ├── findWithFilters(ctx, id, filters)
  ├── findByDate(ctx, id, date)
  ├── findLatest(ctx, id)
  └── getStats(ctx, id)            // Estadisticas
```

### Estimates Module (MAI-008)

Estimaciones periodicas con workflow de aprobacion.

```typescript
// Entities
Estimacion           // Estimaciones con workflow
EstimacionConcepto   // Lineas con acumulados
Generador            // Numeros generadores
Anticipo             // Anticipos
Amortizacion         // Amortizaciones
Retencion            // Retenciones
FondoGarantia        // Fondo de garantia
EstimacionWorkflow   // Historial de estados

// Services
EstimacionService
  ├── createEstimacion(ctx, dto)   // Numero automatico
  ├── findByContrato(ctx, contratoId)
  ├── findWithFilters(ctx, filters)
  ├── findWithDetails(ctx, id)     // Con relaciones
  ├── addConcepto(ctx, id, dto)
  ├── addGenerador(ctx, conceptoId, dto)
  ├── recalculateTotals(ctx, id)   // Llama funcion PG
  ├── submit(ctx, id)              // Workflow
  ├── review(ctx, id)              // Workflow
  ├── approve(ctx, id)             // Workflow
  ├── reject(ctx, id, reason)      // Workflow
  └── getContractSummary(ctx, id)  // Resumen financiero
```

---

## Base Service

Servicio base con CRUD multi-tenant.

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

// Metodos disponibles
BaseService<T>
  ├── findAll(ctx, options?)       // Paginado
  ├── findById(ctx, id)
  ├── findOne(ctx, where)
  ├── find(ctx, options)
  ├── create(ctx, data)
  ├── update(ctx, id, data)
  ├── softDelete(ctx, id)
  ├── hardDelete(ctx, id)
  ├── count(ctx, where?)
  └── exists(ctx, where)

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

---

## SSOT Constants

Sistema de constantes centralizadas.

```typescript
// database.constants.ts
import { DB_SCHEMAS, DB_TABLES, TABLE_REFS } from '@shared/constants';

DB_SCHEMAS.CONSTRUCTION  // 'construction'
DB_TABLES.construction.CONCEPTOS  // 'conceptos'
TABLE_REFS.FRACCIONAMIENTOS  // 'construction.fraccionamientos'

// api.constants.ts
import { API_ROUTES } from '@shared/constants';

API_ROUTES.PRESUPUESTOS.BASE  // '/api/v1/presupuestos'
API_ROUTES.ESTIMACIONES.BY_ID(id)  // '/api/v1/estimaciones/:id'

// enums.constants.ts
import { ROLES, PROJECT_STATUS } from '@shared/constants';

ROLES.ADMIN  // 'admin'
PROJECT_STATUS.IN_PROGRESS  // 'in_progress'
```

---

## Scripts NPM

```bash
# Desarrollo
npm run dev              # Hot-reload con ts-node-dev
npm run build            # Compilar TypeScript
npm run start            # Produccion (dist/)

# Calidad
npm run lint             # ESLint
npm run lint:fix         # ESLint con autofix
npm run test             # Jest
npm run test:watch       # Jest watch mode
npm run test:coverage    # Jest con cobertura

# Base de datos
npm run migration:generate  # Generar migracion
npm run migration:run       # Ejecutar migraciones
npm run migration:revert    # Revertir ultima

# SSOT
npm run validate:constants  # Validar no hardcoding
npm run sync:enums          # Sincronizar a frontend
npm run precommit           # lint + validate
```

---

## Convenciones

### Nomenclatura

| Tipo | Convencion | Ejemplo |
|------|------------|---------|
| Archivos | kebab-case.tipo.ts | `concepto.entity.ts` |
| Clases | PascalCase + sufijo | `ConceptoService` |
| Variables | camelCase | `totalAmount` |
| Constantes | UPPER_SNAKE_CASE | `DB_SCHEMAS` |
| Metodos | camelCase + verbo | `findByContrato` |

### Entity Pattern

```typescript
@Entity({ schema: 'construction', name: 'conceptos' })
@Index(['tenantId', 'code'], { unique: true })
export class Concepto {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ name: 'tenant_id', type: 'uuid' })
  tenantId: string;

  // ... columnas con name: 'snake_case'

  // Soft delete
  @Column({ name: 'deleted_at', type: 'timestamptz', nullable: true })
  deletedAt: Date | null;

  // Relations
  @ManyToOne(() => Tenant)
  @JoinColumn({ name: 'tenant_id' })
  tenant: Tenant;
}
```

### Service Pattern

```typescript
export class MiService extends BaseService<MiEntity> {
  constructor(
    repository: Repository<MiEntity>,
    private readonly otroRepo: Repository<OtroEntity>
  ) {
    super(repository);
  }

  async miMetodo(ctx: ServiceContext, data: MiDto): Promise<MiEntity> {
    // ctx tiene tenantId y userId
    return this.create(ctx, data);
  }
}
```

---

## Seguridad

- Helmet para HTTP security headers
- CORS configurado por dominio
- Rate limiting por IP
- JWT con refresh tokens
- Bcrypt (12 rounds) para passwords
- class-validator para inputs
- RLS para aislamiento de tenants

---

## Testing

```bash
# Ejecutar tests
npm test

# Con cobertura
npm run test:coverage

# Watch mode
npm run test:watch
```

```typescript
// Ejemplo de test
describe('ConceptoService', () => {
  let service: ConceptoService;
  let mockRepo: jest.Mocked<Repository<Concepto>>;

  beforeEach(() => {
    mockRepo = createMockRepository();
    service = new ConceptoService(mockRepo);
  });

  it('should create concepto with level', async () => {
    const ctx = { tenantId: 'uuid', userId: 'uuid' };
    const dto = { code: '001', name: 'Test' };

    mockRepo.save.mockResolvedValue({ ...dto, level: 0 });

    const result = await service.createConcepto(ctx, dto);
    expect(result.level).toBe(0);
  });
});
```

---

## Debugging

### VS Code

```json
{
  "type": "node",
  "request": "launch",
  "name": "Debug Backend",
  "runtimeArgs": ["-r", "ts-node/register"],
  "args": ["${workspaceFolder}/src/server.ts"],
  "env": { "NODE_ENV": "development" }
}
```

### Logs

```typescript
// Configurar en .env
LOG_LEVEL=debug
LOG_FORMAT=dev
```

---

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