Initial commit - erp-construccion-backend
This commit is contained in:
commit
e5bea1fc7d
71
.env.example
Normal file
71
.env.example
Normal file
@ -0,0 +1,71 @@
|
||||
# ============================================================================
|
||||
# BACKEND ENVIRONMENT VARIABLES - ERP Construccion
|
||||
# ============================================================================
|
||||
# Proyecto: construccion
|
||||
# Rango de puertos: 3100 (ver DEVENV-PORTS.md)
|
||||
# Fecha: 2025-12-06
|
||||
# ============================================================================
|
||||
|
||||
# Application
|
||||
NODE_ENV=development
|
||||
APP_PORT=3021
|
||||
APP_HOST=0.0.0.0
|
||||
API_VERSION=v1
|
||||
API_PREFIX=/api/v1
|
||||
|
||||
# Database (Puerto 5433 - diferenciado de erp-core:5432)
|
||||
DATABASE_URL=postgresql://erp_user:erp_dev_password@localhost:5433/erp_construccion
|
||||
DB_HOST=localhost
|
||||
DB_PORT=5433
|
||||
DB_NAME=erp_construccion
|
||||
DB_USER=erp_user
|
||||
DB_PASSWORD=erp_dev_password
|
||||
DB_SYNCHRONIZE=false
|
||||
DB_LOGGING=true
|
||||
|
||||
# Redis (Puerto 6380 - diferenciado de erp-core:6379)
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PORT=6380
|
||||
REDIS_URL=redis://localhost:6380
|
||||
|
||||
# MinIO S3 (Puerto 9100 - diferenciado de erp-core:9000)
|
||||
S3_ENDPOINT=http://localhost:9100
|
||||
S3_ACCESS_KEY=minioadmin
|
||||
S3_SECRET_KEY=minioadmin
|
||||
S3_BUCKET=erp-construccion
|
||||
|
||||
# JWT
|
||||
JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
|
||||
JWT_EXPIRATION=24h
|
||||
JWT_REFRESH_EXPIRATION=7d
|
||||
|
||||
# CORS (Frontend en puerto 5174)
|
||||
CORS_ORIGIN=http://localhost:3020,http://localhost:5174
|
||||
CORS_CREDENTIALS=true
|
||||
|
||||
# Rate Limiting
|
||||
RATE_LIMIT_WINDOW_MS=900000
|
||||
RATE_LIMIT_MAX_REQUESTS=100
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL=debug
|
||||
LOG_FORMAT=dev
|
||||
|
||||
# File Upload
|
||||
MAX_FILE_SIZE=10485760
|
||||
UPLOAD_DIR=./uploads
|
||||
|
||||
# Email (opcional)
|
||||
SMTP_HOST=smtp.gmail.com
|
||||
SMTP_PORT=587
|
||||
SMTP_USER=your-email@example.com
|
||||
SMTP_PASSWORD=your-email-password
|
||||
SMTP_FROM=noreply@example.com
|
||||
|
||||
# Security
|
||||
BCRYPT_ROUNDS=10
|
||||
SESSION_SECRET=your-session-secret-change-this
|
||||
|
||||
# External APIs (futuro)
|
||||
INFONAVIT_API_URL=https://api.infonavit.gob.mx
|
||||
INFONAVIT_API_KEY=your-api-key
|
||||
84
Dockerfile
Normal file
84
Dockerfile
Normal file
@ -0,0 +1,84 @@
|
||||
# =============================================================================
|
||||
# Dockerfile - Backend API
|
||||
# ERP Construccion - Node.js + Express + TypeScript
|
||||
# =============================================================================
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Stage 1: Base
|
||||
# -----------------------------------------------------------------------------
|
||||
FROM node:20-alpine AS base
|
||||
|
||||
# Install dependencies for native modules
|
||||
RUN apk add --no-cache \
|
||||
python3 \
|
||||
make \
|
||||
g++ \
|
||||
curl
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Stage 2: Development
|
||||
# -----------------------------------------------------------------------------
|
||||
FROM base AS development
|
||||
|
||||
# Install all dependencies (including devDependencies)
|
||||
RUN npm ci
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Expose port (standard: 3021 for construccion backend)
|
||||
EXPOSE 3021
|
||||
|
||||
# Development command with hot reload
|
||||
CMD ["npm", "run", "dev"]
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Stage 3: Builder
|
||||
# -----------------------------------------------------------------------------
|
||||
FROM base AS builder
|
||||
|
||||
# Install all dependencies
|
||||
RUN npm ci
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Build TypeScript
|
||||
RUN npm run build
|
||||
|
||||
# Prune devDependencies
|
||||
RUN npm prune --production
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Stage 4: Production
|
||||
# -----------------------------------------------------------------------------
|
||||
FROM node:20-alpine AS production
|
||||
|
||||
# Security: Run as non-root user
|
||||
RUN addgroup -g 1001 -S nodejs && \
|
||||
adduser -S nodejs -u 1001
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy built application
|
||||
COPY --from=builder --chown=nodejs:nodejs /app/dist ./dist
|
||||
COPY --from=builder --chown=nodejs:nodejs /app/node_modules ./node_modules
|
||||
COPY --from=builder --chown=nodejs:nodejs /app/package*.json ./
|
||||
|
||||
# Set user
|
||||
USER nodejs
|
||||
|
||||
# Expose port (standard: 3021 for construccion backend)
|
||||
EXPOSE 3021
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
|
||||
CMD curl -f http://localhost:3021/health || exit 1
|
||||
|
||||
# Production command
|
||||
CMD ["node", "dist/server.js"]
|
||||
461
README.md
Normal file
461
README.md
Normal file
@ -0,0 +1,461 @@
|
||||
# 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
|
||||
16
dist/modules/auth/controllers/auth.controller.d.ts
vendored
Normal file
16
dist/modules/auth/controllers/auth.controller.d.ts
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* AuthController - Controlador de Autenticación
|
||||
*
|
||||
* Endpoints REST para login, register, refresh y logout.
|
||||
* Implementa validación de datos y manejo de errores.
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
import { Router } from 'express';
|
||||
import { DataSource } from 'typeorm';
|
||||
/**
|
||||
* Crear router de autenticación
|
||||
*/
|
||||
export declare function createAuthController(dataSource: DataSource): Router;
|
||||
export default createAuthController;
|
||||
//# sourceMappingURL=auth.controller.d.ts.map
|
||||
1
dist/modules/auth/controllers/auth.controller.d.ts.map
vendored
Normal file
1
dist/modules/auth/controllers/auth.controller.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.controller.d.ts","sourceRoot":"","sources":["../../../../src/modules/auth/controllers/auth.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAarC;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CA+OnE;AAED,eAAe,oBAAoB,CAAC"}
|
||||
237
dist/modules/auth/controllers/auth.controller.js
vendored
Normal file
237
dist/modules/auth/controllers/auth.controller.js
vendored
Normal file
@ -0,0 +1,237 @@
|
||||
"use strict";
|
||||
/**
|
||||
* AuthController - Controlador de Autenticación
|
||||
*
|
||||
* Endpoints REST para login, register, refresh y logout.
|
||||
* Implementa validación de datos y manejo de errores.
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createAuthController = createAuthController;
|
||||
const express_1 = require("express");
|
||||
const auth_service_1 = require("../services/auth.service");
|
||||
const auth_middleware_1 = require("../middleware/auth.middleware");
|
||||
const user_entity_1 = require("../../core/entities/user.entity");
|
||||
const tenant_entity_1 = require("../../core/entities/tenant.entity");
|
||||
const refresh_token_entity_1 = require("../entities/refresh-token.entity");
|
||||
/**
|
||||
* Crear router de autenticación
|
||||
*/
|
||||
function createAuthController(dataSource) {
|
||||
const router = (0, express_1.Router)();
|
||||
// Inicializar repositorios
|
||||
const userRepository = dataSource.getRepository(user_entity_1.User);
|
||||
const tenantRepository = dataSource.getRepository(tenant_entity_1.Tenant);
|
||||
const refreshTokenRepository = dataSource.getRepository(refresh_token_entity_1.RefreshToken);
|
||||
// Inicializar servicio
|
||||
const authService = new auth_service_1.AuthService(userRepository, tenantRepository, refreshTokenRepository);
|
||||
// Inicializar middleware
|
||||
const authMiddleware = new auth_middleware_1.AuthMiddleware(authService, dataSource);
|
||||
/**
|
||||
* POST /auth/login
|
||||
* Login de usuario
|
||||
*/
|
||||
router.post('/login', async (req, res, next) => {
|
||||
try {
|
||||
const dto = req.body;
|
||||
if (!dto.email || !dto.password) {
|
||||
res.status(400).json({
|
||||
error: 'Bad Request',
|
||||
message: 'Email and password are required',
|
||||
});
|
||||
return;
|
||||
}
|
||||
const result = await authService.login(dto);
|
||||
res.status(200).json({ success: true, data: result });
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof Error) {
|
||||
if (error.message === 'Invalid credentials') {
|
||||
res.status(401).json({ error: 'Unauthorized', message: 'Invalid email or password' });
|
||||
return;
|
||||
}
|
||||
if (error.message === 'User is not active') {
|
||||
res.status(403).json({ error: 'Forbidden', message: 'User account is disabled' });
|
||||
return;
|
||||
}
|
||||
if (error.message === 'No tenant specified' || error.message === 'Tenant not found or inactive') {
|
||||
res.status(400).json({ error: 'Bad Request', message: error.message });
|
||||
return;
|
||||
}
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* POST /auth/register
|
||||
* Registro de nuevo usuario
|
||||
*/
|
||||
router.post('/register', async (req, res, next) => {
|
||||
try {
|
||||
const dto = req.body;
|
||||
if (!dto.email || !dto.password || !dto.firstName || !dto.lastName || !dto.tenantId) {
|
||||
res.status(400).json({
|
||||
error: 'Bad Request',
|
||||
message: 'Email, password, firstName, lastName and tenantId are required',
|
||||
});
|
||||
return;
|
||||
}
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(dto.email)) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Invalid email format' });
|
||||
return;
|
||||
}
|
||||
if (dto.password.length < 8) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Password must be at least 8 characters' });
|
||||
return;
|
||||
}
|
||||
const result = await authService.register(dto);
|
||||
res.status(201).json({ success: true, data: result });
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof Error) {
|
||||
if (error.message === 'Email already registered') {
|
||||
res.status(409).json({ error: 'Conflict', message: 'Email is already registered' });
|
||||
return;
|
||||
}
|
||||
if (error.message === 'Tenant not found') {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Invalid tenant ID' });
|
||||
return;
|
||||
}
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* POST /auth/refresh
|
||||
* Renovar access token usando refresh token
|
||||
*/
|
||||
router.post('/refresh', async (req, res, next) => {
|
||||
try {
|
||||
const dto = req.body;
|
||||
if (!dto.refreshToken) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Refresh token is required' });
|
||||
return;
|
||||
}
|
||||
const result = await authService.refresh(dto);
|
||||
res.status(200).json({ success: true, data: result });
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof Error) {
|
||||
if (error.message === 'Invalid refresh token' || error.message === 'Refresh token expired or revoked') {
|
||||
res.status(401).json({ error: 'Unauthorized', message: error.message });
|
||||
return;
|
||||
}
|
||||
if (error.message === 'User not found or inactive') {
|
||||
res.status(401).json({ error: 'Unauthorized', message: 'User account is disabled or deleted' });
|
||||
return;
|
||||
}
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* POST /auth/logout
|
||||
* Cerrar sesión (revocar refresh token)
|
||||
*/
|
||||
router.post('/logout', authMiddleware.authenticate, async (req, res, next) => {
|
||||
try {
|
||||
const { refreshToken } = req.body;
|
||||
if (refreshToken) {
|
||||
await authService.logout(refreshToken);
|
||||
}
|
||||
res.status(200).json({ success: true, message: 'Logged out successfully' });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* POST /auth/change-password
|
||||
* Cambiar contraseña (requiere autenticación)
|
||||
*/
|
||||
router.post('/change-password', authMiddleware.authenticate, async (req, res, next) => {
|
||||
try {
|
||||
const dto = req.body;
|
||||
const userId = req.user?.sub;
|
||||
if (!userId) {
|
||||
res.status(401).json({ error: 'Unauthorized', message: 'User not authenticated' });
|
||||
return;
|
||||
}
|
||||
if (!dto.currentPassword || !dto.newPassword) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Current password and new password are required' });
|
||||
return;
|
||||
}
|
||||
if (dto.newPassword.length < 8) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'New password must be at least 8 characters' });
|
||||
return;
|
||||
}
|
||||
await authService.changePassword(userId, dto);
|
||||
res.status(200).json({ success: true, message: 'Password changed successfully' });
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof Error && error.message === 'Current password is incorrect') {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Current password is incorrect' });
|
||||
return;
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* GET /auth/me
|
||||
* Obtener información del usuario autenticado
|
||||
*/
|
||||
router.get('/me', authMiddleware.authenticate, async (req, res, next) => {
|
||||
try {
|
||||
const userId = req.user?.sub;
|
||||
if (!userId) {
|
||||
res.status(401).json({ error: 'Unauthorized', message: 'User not authenticated' });
|
||||
return;
|
||||
}
|
||||
const user = await userRepository.findOne({
|
||||
where: { id: userId },
|
||||
select: ['id', 'email', 'firstName', 'lastName', 'isActive', 'createdAt'],
|
||||
});
|
||||
if (!user) {
|
||||
res.status(404).json({ error: 'Not Found', message: 'User not found' });
|
||||
return;
|
||||
}
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
data: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
firstName: user.firstName,
|
||||
lastName: user.lastName,
|
||||
roles: req.user?.roles || [],
|
||||
tenantId: req.tenantId,
|
||||
},
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* GET /auth/verify
|
||||
* Verificar si el token es válido
|
||||
*/
|
||||
router.get('/verify', authMiddleware.authenticate, (req, res) => {
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
data: {
|
||||
valid: true,
|
||||
user: {
|
||||
id: req.user?.sub,
|
||||
email: req.user?.email,
|
||||
roles: req.user?.roles,
|
||||
},
|
||||
tenantId: req.tenantId,
|
||||
},
|
||||
});
|
||||
});
|
||||
return router;
|
||||
}
|
||||
exports.default = createAuthController;
|
||||
//# sourceMappingURL=auth.controller.js.map
|
||||
1
dist/modules/auth/controllers/auth.controller.js.map
vendored
Normal file
1
dist/modules/auth/controllers/auth.controller.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
5
dist/modules/auth/controllers/index.d.ts
vendored
Normal file
5
dist/modules/auth/controllers/index.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Auth Controllers - Export
|
||||
*/
|
||||
export * from './auth.controller';
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
dist/modules/auth/controllers/index.d.ts.map
vendored
Normal file
1
dist/modules/auth/controllers/index.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/auth/controllers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,mBAAmB,CAAC"}
|
||||
21
dist/modules/auth/controllers/index.js
vendored
Normal file
21
dist/modules/auth/controllers/index.js
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Auth Controllers - Export
|
||||
*/
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("./auth.controller"), exports);
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
dist/modules/auth/controllers/index.js.map
vendored
Normal file
1
dist/modules/auth/controllers/index.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/auth/controllers/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;AAEH,oDAAkC"}
|
||||
62
dist/modules/auth/dto/auth.dto.d.ts
vendored
Normal file
62
dist/modules/auth/dto/auth.dto.d.ts
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Auth DTOs - Data Transfer Objects para autenticación
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
export interface LoginDto {
|
||||
email: string;
|
||||
password: string;
|
||||
tenantId?: string;
|
||||
}
|
||||
export interface RegisterDto {
|
||||
email: string;
|
||||
password: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
tenantId: string;
|
||||
}
|
||||
export interface RefreshTokenDto {
|
||||
refreshToken: string;
|
||||
}
|
||||
export interface ChangePasswordDto {
|
||||
currentPassword: string;
|
||||
newPassword: string;
|
||||
}
|
||||
export interface ResetPasswordRequestDto {
|
||||
email: string;
|
||||
}
|
||||
export interface ResetPasswordDto {
|
||||
token: string;
|
||||
newPassword: string;
|
||||
}
|
||||
export interface TokenPayload {
|
||||
sub: string;
|
||||
email: string;
|
||||
tenantId: string;
|
||||
roles: string[];
|
||||
type: 'access' | 'refresh';
|
||||
iat?: number;
|
||||
exp?: number;
|
||||
}
|
||||
export interface AuthResponse {
|
||||
accessToken: string;
|
||||
refreshToken: string;
|
||||
expiresIn: number;
|
||||
user: {
|
||||
id: string;
|
||||
email: string;
|
||||
firstName: string;
|
||||
lastName: string;
|
||||
roles: string[];
|
||||
};
|
||||
tenant: {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
export interface TokenValidationResult {
|
||||
valid: boolean;
|
||||
payload?: TokenPayload;
|
||||
error?: string;
|
||||
}
|
||||
//# sourceMappingURL=auth.dto.d.ts.map
|
||||
1
dist/modules/auth/dto/auth.dto.d.ts.map
vendored
Normal file
1
dist/modules/auth/dto/auth.dto.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.dto.d.ts","sourceRoot":"","sources":["../../../../src/modules/auth/dto/auth.dto.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE;QACJ,EAAE,EAAE,MAAM,CAAC;QACX,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,EAAE,CAAC;KACjB,CAAC;IACF,MAAM,EAAE;QACN,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
|
||||
8
dist/modules/auth/dto/auth.dto.js
vendored
Normal file
8
dist/modules/auth/dto/auth.dto.js
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Auth DTOs - Data Transfer Objects para autenticación
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=auth.dto.js.map
|
||||
1
dist/modules/auth/dto/auth.dto.js.map
vendored
Normal file
1
dist/modules/auth/dto/auth.dto.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.dto.js","sourceRoot":"","sources":["../../../../src/modules/auth/dto/auth.dto.ts"],"names":[],"mappings":";AAAA;;;;GAIG"}
|
||||
8
dist/modules/auth/entities/index.d.ts
vendored
Normal file
8
dist/modules/auth/entities/index.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Auth Entities - Export
|
||||
*/
|
||||
export { RefreshToken } from './refresh-token.entity';
|
||||
export { Role } from './role.entity';
|
||||
export { Permission } from './permission.entity';
|
||||
export { UserRole } from './user-role.entity';
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
dist/modules/auth/entities/index.d.ts.map
vendored
Normal file
1
dist/modules/auth/entities/index.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/auth/entities/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC"}
|
||||
15
dist/modules/auth/entities/index.js
vendored
Normal file
15
dist/modules/auth/entities/index.js
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Auth Entities - Export
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UserRole = exports.Permission = exports.Role = exports.RefreshToken = void 0;
|
||||
var refresh_token_entity_1 = require("./refresh-token.entity");
|
||||
Object.defineProperty(exports, "RefreshToken", { enumerable: true, get: function () { return refresh_token_entity_1.RefreshToken; } });
|
||||
var role_entity_1 = require("./role.entity");
|
||||
Object.defineProperty(exports, "Role", { enumerable: true, get: function () { return role_entity_1.Role; } });
|
||||
var permission_entity_1 = require("./permission.entity");
|
||||
Object.defineProperty(exports, "Permission", { enumerable: true, get: function () { return permission_entity_1.Permission; } });
|
||||
var user_role_entity_1 = require("./user-role.entity");
|
||||
Object.defineProperty(exports, "UserRole", { enumerable: true, get: function () { return user_role_entity_1.UserRole; } });
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
dist/modules/auth/entities/index.js.map
vendored
Normal file
1
dist/modules/auth/entities/index.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/auth/entities/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,+DAAsD;AAA7C,oHAAA,YAAY,OAAA;AACrB,6CAAqC;AAA5B,mGAAA,IAAI,OAAA;AACb,yDAAiD;AAAxC,+GAAA,UAAU,OAAA;AACnB,uDAA8C;AAArC,4GAAA,QAAQ,OAAA"}
|
||||
15
dist/modules/auth/entities/permission.entity.d.ts
vendored
Normal file
15
dist/modules/auth/entities/permission.entity.d.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Permission Entity
|
||||
* Permisos granulares del sistema
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
export declare class Permission {
|
||||
id: string;
|
||||
code: string;
|
||||
name: string;
|
||||
description: string;
|
||||
module: string;
|
||||
createdAt: Date;
|
||||
}
|
||||
//# sourceMappingURL=permission.entity.d.ts.map
|
||||
1
dist/modules/auth/entities/permission.entity.d.ts.map
vendored
Normal file
1
dist/modules/auth/entities/permission.entity.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"permission.entity.d.ts","sourceRoot":"","sources":["../../../../src/modules/auth/entities/permission.entity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,qBACa,UAAU;IAErB,EAAE,EAAE,MAAM,CAAC;IAGX,IAAI,EAAE,MAAM,CAAC;IAGb,IAAI,EAAE,MAAM,CAAC;IAGb,WAAW,EAAE,MAAM,CAAC;IAGpB,MAAM,EAAE,MAAM,CAAC;IAGf,SAAS,EAAE,IAAI,CAAC;CACjB"}
|
||||
56
dist/modules/auth/entities/permission.entity.js
vendored
Normal file
56
dist/modules/auth/entities/permission.entity.js
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Permission Entity
|
||||
* Permisos granulares del sistema
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Permission = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
let Permission = class Permission {
|
||||
id;
|
||||
code;
|
||||
name;
|
||||
description;
|
||||
module;
|
||||
createdAt;
|
||||
};
|
||||
exports.Permission = Permission;
|
||||
__decorate([
|
||||
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
||||
__metadata("design:type", String)
|
||||
], Permission.prototype, "id", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'varchar', length: 100, unique: true }),
|
||||
__metadata("design:type", String)
|
||||
], Permission.prototype, "code", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'varchar', length: 200 }),
|
||||
__metadata("design:type", String)
|
||||
], Permission.prototype, "name", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'text', nullable: true }),
|
||||
__metadata("design:type", String)
|
||||
], Permission.prototype, "description", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'varchar', length: 50 }),
|
||||
__metadata("design:type", String)
|
||||
], Permission.prototype, "module", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.CreateDateColumn)({ name: 'created_at', type: 'timestamptz' }),
|
||||
__metadata("design:type", Date)
|
||||
], Permission.prototype, "createdAt", void 0);
|
||||
exports.Permission = Permission = __decorate([
|
||||
(0, typeorm_1.Entity)({ schema: 'auth', name: 'permissions' })
|
||||
], Permission);
|
||||
//# sourceMappingURL=permission.entity.js.map
|
||||
1
dist/modules/auth/entities/permission.entity.js.map
vendored
Normal file
1
dist/modules/auth/entities/permission.entity.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"permission.entity.js","sourceRoot":"","sources":["../../../../src/modules/auth/entities/permission.entity.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;AAEH,qCAKiB;AAGV,IAAM,UAAU,GAAhB,MAAM,UAAU;IAErB,EAAE,CAAS;IAGX,IAAI,CAAS;IAGb,IAAI,CAAS;IAGb,WAAW,CAAS;IAGpB,MAAM,CAAS;IAGf,SAAS,CAAO;CACjB,CAAA;AAlBY,gCAAU;AAErB;IADC,IAAA,gCAAsB,EAAC,MAAM,CAAC;;sCACpB;AAGX;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;;wCAC1C;AAGb;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;;wCAC5B;AAGb;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;+CACrB;AAGpB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;;0CACzB;AAGf;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;8BACnD,IAAI;6CAAC;qBAjBL,UAAU;IADtB,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;GACnC,UAAU,CAkBtB"}
|
||||
33
dist/modules/auth/entities/refresh-token.entity.d.ts
vendored
Normal file
33
dist/modules/auth/entities/refresh-token.entity.d.ts
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* RefreshToken Entity
|
||||
*
|
||||
* Almacena refresh tokens para autenticación JWT.
|
||||
* Permite revocar tokens y gestionar sesiones.
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
import { User } from '../../core/entities/user.entity';
|
||||
export declare class RefreshToken {
|
||||
id: string;
|
||||
userId: string;
|
||||
user: User;
|
||||
token: string;
|
||||
expiresAt: Date;
|
||||
revokedAt: Date | null;
|
||||
createdAt: Date;
|
||||
userAgent: string | null;
|
||||
ipAddress: string | null;
|
||||
/**
|
||||
* Verificar si el token está expirado
|
||||
*/
|
||||
isExpired(): boolean;
|
||||
/**
|
||||
* Verificar si el token está revocado
|
||||
*/
|
||||
isRevoked(): boolean;
|
||||
/**
|
||||
* Verificar si el token es válido
|
||||
*/
|
||||
isValid(): boolean;
|
||||
}
|
||||
//# sourceMappingURL=refresh-token.entity.d.ts.map
|
||||
1
dist/modules/auth/entities/refresh-token.entity.d.ts.map
vendored
Normal file
1
dist/modules/auth/entities/refresh-token.entity.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"refresh-token.entity.d.ts","sourceRoot":"","sources":["../../../../src/modules/auth/entities/refresh-token.entity.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAWH,OAAO,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAEvD,qBAGa,YAAY;IAEvB,EAAE,EAAE,MAAM,CAAC;IAGX,MAAM,EAAE,MAAM,CAAC;IAIf,IAAI,EAAE,IAAI,CAAC;IAGX,KAAK,EAAE,MAAM,CAAC;IAGd,SAAS,EAAE,IAAI,CAAC;IAGhB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IAGvB,SAAS,EAAE,IAAI,CAAC;IAGhB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAGzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,OAAO,IAAI,OAAO;CAGnB"}
|
||||
95
dist/modules/auth/entities/refresh-token.entity.js
vendored
Normal file
95
dist/modules/auth/entities/refresh-token.entity.js
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
"use strict";
|
||||
/**
|
||||
* RefreshToken Entity
|
||||
*
|
||||
* Almacena refresh tokens para autenticación JWT.
|
||||
* Permite revocar tokens y gestionar sesiones.
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.RefreshToken = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
const user_entity_1 = require("../../core/entities/user.entity");
|
||||
let RefreshToken = class RefreshToken {
|
||||
id;
|
||||
userId;
|
||||
user;
|
||||
token;
|
||||
expiresAt;
|
||||
revokedAt;
|
||||
createdAt;
|
||||
userAgent;
|
||||
ipAddress;
|
||||
/**
|
||||
* Verificar si el token está expirado
|
||||
*/
|
||||
isExpired() {
|
||||
return this.expiresAt < new Date();
|
||||
}
|
||||
/**
|
||||
* Verificar si el token está revocado
|
||||
*/
|
||||
isRevoked() {
|
||||
return this.revokedAt !== null;
|
||||
}
|
||||
/**
|
||||
* Verificar si el token es válido
|
||||
*/
|
||||
isValid() {
|
||||
return !this.isExpired() && !this.isRevoked();
|
||||
}
|
||||
};
|
||||
exports.RefreshToken = RefreshToken;
|
||||
__decorate([
|
||||
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
||||
__metadata("design:type", String)
|
||||
], RefreshToken.prototype, "id", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'user_id', type: 'uuid' }),
|
||||
__metadata("design:type", String)
|
||||
], RefreshToken.prototype, "userId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => user_entity_1.User, { onDelete: 'CASCADE' }),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'user_id' }),
|
||||
__metadata("design:type", user_entity_1.User)
|
||||
], RefreshToken.prototype, "user", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'text' }),
|
||||
__metadata("design:type", String)
|
||||
], RefreshToken.prototype, "token", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'expires_at', type: 'timestamptz' }),
|
||||
__metadata("design:type", Date)
|
||||
], RefreshToken.prototype, "expiresAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'revoked_at', type: 'timestamptz', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], RefreshToken.prototype, "revokedAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.CreateDateColumn)({ name: 'created_at', type: 'timestamptz' }),
|
||||
__metadata("design:type", Date)
|
||||
], RefreshToken.prototype, "createdAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'user_agent', type: 'varchar', length: 500, nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], RefreshToken.prototype, "userAgent", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'ip_address', type: 'varchar', length: 45, nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], RefreshToken.prototype, "ipAddress", void 0);
|
||||
exports.RefreshToken = RefreshToken = __decorate([
|
||||
(0, typeorm_1.Entity)({ name: 'refresh_tokens', schema: 'auth' }),
|
||||
(0, typeorm_1.Index)(['userId', 'revokedAt']),
|
||||
(0, typeorm_1.Index)(['token'])
|
||||
], RefreshToken);
|
||||
//# sourceMappingURL=refresh-token.entity.js.map
|
||||
1
dist/modules/auth/entities/refresh-token.entity.js.map
vendored
Normal file
1
dist/modules/auth/entities/refresh-token.entity.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"refresh-token.entity.js","sourceRoot":"","sources":["../../../../src/modules/auth/entities/refresh-token.entity.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;;;;;;;;;;AAEH,qCAQiB;AACjB,iEAAuD;AAKhD,IAAM,YAAY,GAAlB,MAAM,YAAY;IAEvB,EAAE,CAAS;IAGX,MAAM,CAAS;IAIf,IAAI,CAAO;IAGX,KAAK,CAAS;IAGd,SAAS,CAAO;IAGhB,SAAS,CAAc;IAGvB,SAAS,CAAO;IAGhB,SAAS,CAAgB;IAGzB,SAAS,CAAgB;IAEzB;;OAEG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,SAAS;QACP,OAAO,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,OAAO;QACL,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IAChD,CAAC;CACF,CAAA;AAjDY,oCAAY;AAEvB;IADC,IAAA,gCAAsB,EAAC,MAAM,CAAC;;wCACpB;AAGX;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;4CAC3B;AAIf;IAFC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,kBAAI,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAC9C,IAAA,oBAAU,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;8BAC1B,kBAAI;0CAAC;AAGX;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;2CACX;AAGd;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;8BACzC,IAAI;+CAAC;AAGhB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;+CAC7C;AAGvB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;8BACnD,IAAI;+CAAC;AAGhB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;+CACpD;AAGzB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;+CACnD;uBA3Bd,YAAY;IAHxB,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAClD,IAAA,eAAK,EAAC,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC9B,IAAA,eAAK,EAAC,CAAC,OAAO,CAAC,CAAC;GACJ,YAAY,CAiDxB"}
|
||||
21
dist/modules/auth/entities/role.entity.d.ts
vendored
Normal file
21
dist/modules/auth/entities/role.entity.d.ts
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Role Entity
|
||||
* Roles del sistema para RBAC
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
import { Permission } from './permission.entity';
|
||||
import { UserRole } from './user-role.entity';
|
||||
export declare class Role {
|
||||
id: string;
|
||||
code: string;
|
||||
name: string;
|
||||
description: string;
|
||||
isSystem: boolean;
|
||||
isActive: boolean;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
permissions: Permission[];
|
||||
userRoles: UserRole[];
|
||||
}
|
||||
//# sourceMappingURL=role.entity.d.ts.map
|
||||
1
dist/modules/auth/entities/role.entity.d.ts.map
vendored
Normal file
1
dist/modules/auth/entities/role.entity.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"role.entity.d.ts","sourceRoot":"","sources":["../../../../src/modules/auth/entities/role.entity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,qBACa,IAAI;IAEf,EAAE,EAAE,MAAM,CAAC;IAGX,IAAI,EAAE,MAAM,CAAC;IAGb,IAAI,EAAE,MAAM,CAAC;IAGb,WAAW,EAAE,MAAM,CAAC;IAGpB,QAAQ,EAAE,OAAO,CAAC;IAGlB,QAAQ,EAAE,OAAO,CAAC;IAGlB,SAAS,EAAE,IAAI,CAAC;IAGhB,SAAS,EAAE,IAAI,CAAC;IAShB,WAAW,EAAE,UAAU,EAAE,CAAC;IAG1B,SAAS,EAAE,QAAQ,EAAE,CAAC;CACvB"}
|
||||
84
dist/modules/auth/entities/role.entity.js
vendored
Normal file
84
dist/modules/auth/entities/role.entity.js
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Role Entity
|
||||
* Roles del sistema para RBAC
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Role = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
const permission_entity_1 = require("./permission.entity");
|
||||
const user_role_entity_1 = require("./user-role.entity");
|
||||
let Role = class Role {
|
||||
id;
|
||||
code;
|
||||
name;
|
||||
description;
|
||||
isSystem;
|
||||
isActive;
|
||||
createdAt;
|
||||
updatedAt;
|
||||
// Relations
|
||||
permissions;
|
||||
userRoles;
|
||||
};
|
||||
exports.Role = Role;
|
||||
__decorate([
|
||||
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
||||
__metadata("design:type", String)
|
||||
], Role.prototype, "id", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'varchar', length: 50, unique: true }),
|
||||
__metadata("design:type", String)
|
||||
], Role.prototype, "code", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'varchar', length: 100 }),
|
||||
__metadata("design:type", String)
|
||||
], Role.prototype, "name", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'text', nullable: true }),
|
||||
__metadata("design:type", String)
|
||||
], Role.prototype, "description", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'is_system', type: 'boolean', default: false }),
|
||||
__metadata("design:type", Boolean)
|
||||
], Role.prototype, "isSystem", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'is_active', type: 'boolean', default: true }),
|
||||
__metadata("design:type", Boolean)
|
||||
], Role.prototype, "isActive", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.CreateDateColumn)({ name: 'created_at', type: 'timestamptz' }),
|
||||
__metadata("design:type", Date)
|
||||
], Role.prototype, "createdAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.UpdateDateColumn)({ name: 'updated_at', type: 'timestamptz' }),
|
||||
__metadata("design:type", Date)
|
||||
], Role.prototype, "updatedAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToMany)(() => permission_entity_1.Permission),
|
||||
(0, typeorm_1.JoinTable)({
|
||||
name: 'role_permissions',
|
||||
joinColumn: { name: 'role_id', referencedColumnName: 'id' },
|
||||
inverseJoinColumn: { name: 'permission_id', referencedColumnName: 'id' },
|
||||
}),
|
||||
__metadata("design:type", Array)
|
||||
], Role.prototype, "permissions", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.OneToMany)(() => user_role_entity_1.UserRole, (userRole) => userRole.role),
|
||||
__metadata("design:type", Array)
|
||||
], Role.prototype, "userRoles", void 0);
|
||||
exports.Role = Role = __decorate([
|
||||
(0, typeorm_1.Entity)({ schema: 'auth', name: 'roles' })
|
||||
], Role);
|
||||
//# sourceMappingURL=role.entity.js.map
|
||||
1
dist/modules/auth/entities/role.entity.js.map
vendored
Normal file
1
dist/modules/auth/entities/role.entity.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"role.entity.js","sourceRoot":"","sources":["../../../../src/modules/auth/entities/role.entity.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;AAEH,qCASiB;AACjB,2DAAiD;AACjD,yDAA8C;AAGvC,IAAM,IAAI,GAAV,MAAM,IAAI;IAEf,EAAE,CAAS;IAGX,IAAI,CAAS;IAGb,IAAI,CAAS;IAGb,WAAW,CAAS;IAGpB,QAAQ,CAAU;IAGlB,QAAQ,CAAU;IAGlB,SAAS,CAAO;IAGhB,SAAS,CAAO;IAEhB,YAAY;IAOZ,WAAW,CAAe;IAG1B,SAAS,CAAa;CACvB,CAAA;AApCY,oBAAI;AAEf;IADC,IAAA,gCAAsB,EAAC,MAAM,CAAC;;gCACpB;AAGX;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;;kCACzC;AAGb;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;;kCAC5B;AAGb;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;yCACrB;AAGpB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;;sCAC7C;AAGlB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;;sCAC5C;AAGlB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;8BACnD,IAAI;uCAAC;AAGhB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;8BACnD,IAAI;uCAAC;AAShB;IANC,IAAA,oBAAU,EAAC,GAAG,EAAE,CAAC,8BAAU,CAAC;IAC5B,IAAA,mBAAS,EAAC;QACT,IAAI,EAAE,kBAAkB;QACxB,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,oBAAoB,EAAE,IAAI,EAAE;QAC3D,iBAAiB,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,oBAAoB,EAAE,IAAI,EAAE;KACzE,CAAC;;yCACwB;AAG1B;IADC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,2BAAQ,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;;uCACjC;eAnCX,IAAI;IADhB,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;GAC7B,IAAI,CAoChB"}
|
||||
21
dist/modules/auth/entities/user-role.entity.d.ts
vendored
Normal file
21
dist/modules/auth/entities/user-role.entity.d.ts
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
/**
|
||||
* UserRole Entity
|
||||
* Relación usuarios-roles con soporte multi-tenant
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
import { User } from '../../core/entities/user.entity';
|
||||
import { Role } from './role.entity';
|
||||
import { Tenant } from '../../core/entities/tenant.entity';
|
||||
export declare class UserRole {
|
||||
id: string;
|
||||
userId: string;
|
||||
roleId: string;
|
||||
tenantId: string;
|
||||
assignedBy: string;
|
||||
assignedAt: Date;
|
||||
user: User;
|
||||
role: Role;
|
||||
tenant: Tenant;
|
||||
}
|
||||
//# sourceMappingURL=user-role.entity.d.ts.map
|
||||
1
dist/modules/auth/entities/user-role.entity.d.ts.map
vendored
Normal file
1
dist/modules/auth/entities/user-role.entity.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"user-role.entity.d.ts","sourceRoot":"","sources":["../../../../src/modules/auth/entities/user-role.entity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH,OAAO,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAE3D,qBAEa,QAAQ;IAEnB,EAAE,EAAE,MAAM,CAAC;IAGX,MAAM,EAAE,MAAM,CAAC;IAGf,MAAM,EAAE,MAAM,CAAC;IAGf,QAAQ,EAAE,MAAM,CAAC;IAGjB,UAAU,EAAE,MAAM,CAAC;IAGnB,UAAU,EAAE,IAAI,CAAC;IAKjB,IAAI,EAAE,IAAI,CAAC;IAIX,IAAI,EAAE,IAAI,CAAC;IAIX,MAAM,EAAE,MAAM,CAAC;CAChB"}
|
||||
79
dist/modules/auth/entities/user-role.entity.js
vendored
Normal file
79
dist/modules/auth/entities/user-role.entity.js
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
"use strict";
|
||||
/**
|
||||
* UserRole Entity
|
||||
* Relación usuarios-roles con soporte multi-tenant
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.UserRole = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
const user_entity_1 = require("../../core/entities/user.entity");
|
||||
const role_entity_1 = require("./role.entity");
|
||||
const tenant_entity_1 = require("../../core/entities/tenant.entity");
|
||||
let UserRole = class UserRole {
|
||||
id;
|
||||
userId;
|
||||
roleId;
|
||||
tenantId;
|
||||
assignedBy;
|
||||
assignedAt;
|
||||
// Relations
|
||||
user;
|
||||
role;
|
||||
tenant;
|
||||
};
|
||||
exports.UserRole = UserRole;
|
||||
__decorate([
|
||||
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
||||
__metadata("design:type", String)
|
||||
], UserRole.prototype, "id", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'user_id', type: 'uuid' }),
|
||||
__metadata("design:type", String)
|
||||
], UserRole.prototype, "userId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'role_id', type: 'uuid' }),
|
||||
__metadata("design:type", String)
|
||||
], UserRole.prototype, "roleId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'tenant_id', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", String)
|
||||
], UserRole.prototype, "tenantId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'assigned_by', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", String)
|
||||
], UserRole.prototype, "assignedBy", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.CreateDateColumn)({ name: 'assigned_at', type: 'timestamptz' }),
|
||||
__metadata("design:type", Date)
|
||||
], UserRole.prototype, "assignedAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => user_entity_1.User, { onDelete: 'CASCADE' }),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'user_id' }),
|
||||
__metadata("design:type", user_entity_1.User)
|
||||
], UserRole.prototype, "user", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => role_entity_1.Role, (role) => role.userRoles, { onDelete: 'CASCADE' }),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'role_id' }),
|
||||
__metadata("design:type", role_entity_1.Role)
|
||||
], UserRole.prototype, "role", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => tenant_entity_1.Tenant, { onDelete: 'CASCADE' }),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'tenant_id' }),
|
||||
__metadata("design:type", tenant_entity_1.Tenant)
|
||||
], UserRole.prototype, "tenant", void 0);
|
||||
exports.UserRole = UserRole = __decorate([
|
||||
(0, typeorm_1.Entity)({ schema: 'auth', name: 'user_roles' }),
|
||||
(0, typeorm_1.Index)(['userId', 'roleId', 'tenantId'], { unique: true })
|
||||
], UserRole);
|
||||
//# sourceMappingURL=user-role.entity.js.map
|
||||
1
dist/modules/auth/entities/user-role.entity.js.map
vendored
Normal file
1
dist/modules/auth/entities/user-role.entity.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"user-role.entity.js","sourceRoot":"","sources":["../../../../src/modules/auth/entities/user-role.entity.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;AAEH,qCAQiB;AACjB,iEAAuD;AACvD,+CAAqC;AACrC,qEAA2D;AAIpD,IAAM,QAAQ,GAAd,MAAM,QAAQ;IAEnB,EAAE,CAAS;IAGX,MAAM,CAAS;IAGf,MAAM,CAAS;IAGf,QAAQ,CAAS;IAGjB,UAAU,CAAS;IAGnB,UAAU,CAAO;IAEjB,YAAY;IAGZ,IAAI,CAAO;IAIX,IAAI,CAAO;IAIX,MAAM,CAAS;CAChB,CAAA;AA/BY,4BAAQ;AAEnB;IADC,IAAA,gCAAsB,EAAC,MAAM,CAAC;;oCACpB;AAGX;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;wCAC3B;AAGf;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;wCAC3B;AAGf;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;0CAC3C;AAGjB;IADC,IAAA,gBAAM,EAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;4CAC3C;AAGnB;IADC,IAAA,0BAAgB,EAAC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;8BACnD,IAAI;4CAAC;AAKjB;IAFC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,kBAAI,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAC9C,IAAA,oBAAU,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;8BAC1B,kBAAI;sCAAC;AAIX;IAFC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,kBAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IACxE,IAAA,oBAAU,EAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;8BAC1B,kBAAI;sCAAC;AAIX;IAFC,IAAA,mBAAS,EAAC,GAAG,EAAE,CAAC,sBAAM,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAChD,IAAA,oBAAU,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;8BAC1B,sBAAM;wCAAC;mBA9BJ,QAAQ;IAFpB,IAAA,gBAAM,EAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC9C,IAAA,eAAK,EAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;GAC7C,QAAQ,CA+BpB"}
|
||||
14
dist/modules/auth/index.d.ts
vendored
Normal file
14
dist/modules/auth/index.d.ts
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Auth Module - Main Exports
|
||||
*
|
||||
* Módulo de autenticación con JWT y refresh tokens.
|
||||
* Implementa multi-tenancy con RLS.
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
export * from './dto/auth.dto';
|
||||
export { RefreshToken } from './entities/refresh-token.entity';
|
||||
export { AuthService } from './services/auth.service';
|
||||
export { AuthMiddleware, createAuthMiddleware } from './middleware/auth.middleware';
|
||||
export { createAuthController } from './controllers/auth.controller';
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
dist/modules/auth/index.d.ts.map
vendored
Normal file
1
dist/modules/auth/index.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/modules/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC"}
|
||||
36
dist/modules/auth/index.js
vendored
Normal file
36
dist/modules/auth/index.js
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Auth Module - Main Exports
|
||||
*
|
||||
* Módulo de autenticación con JWT y refresh tokens.
|
||||
* Implementa multi-tenancy con RLS.
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createAuthController = exports.createAuthMiddleware = exports.AuthMiddleware = exports.AuthService = exports.RefreshToken = void 0;
|
||||
__exportStar(require("./dto/auth.dto"), exports);
|
||||
var refresh_token_entity_1 = require("./entities/refresh-token.entity");
|
||||
Object.defineProperty(exports, "RefreshToken", { enumerable: true, get: function () { return refresh_token_entity_1.RefreshToken; } });
|
||||
var auth_service_1 = require("./services/auth.service");
|
||||
Object.defineProperty(exports, "AuthService", { enumerable: true, get: function () { return auth_service_1.AuthService; } });
|
||||
var auth_middleware_1 = require("./middleware/auth.middleware");
|
||||
Object.defineProperty(exports, "AuthMiddleware", { enumerable: true, get: function () { return auth_middleware_1.AuthMiddleware; } });
|
||||
Object.defineProperty(exports, "createAuthMiddleware", { enumerable: true, get: function () { return auth_middleware_1.createAuthMiddleware; } });
|
||||
var auth_controller_1 = require("./controllers/auth.controller");
|
||||
Object.defineProperty(exports, "createAuthController", { enumerable: true, get: function () { return auth_controller_1.createAuthController; } });
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
dist/modules/auth/index.js.map
vendored
Normal file
1
dist/modules/auth/index.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/modules/auth/index.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;;;;;;;;;;;;;;;AAEH,iDAA+B;AAC/B,wEAA+D;AAAtD,oHAAA,YAAY,OAAA;AACrB,wDAAsD;AAA7C,2GAAA,WAAW,OAAA;AACpB,gEAAoF;AAA3E,iHAAA,cAAc,OAAA;AAAE,uHAAA,oBAAoB,OAAA;AAC7C,iEAAqE;AAA5D,uHAAA,oBAAoB,OAAA"}
|
||||
58
dist/modules/auth/middleware/auth.middleware.d.ts
vendored
Normal file
58
dist/modules/auth/middleware/auth.middleware.d.ts
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Auth Middleware - Middleware de Autenticación
|
||||
*
|
||||
* Middleware para Express que valida JWT y extrae información del usuario.
|
||||
* Configura el tenant_id para RLS en PostgreSQL.
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { DataSource } from 'typeorm';
|
||||
import { AuthService } from '../services/auth.service';
|
||||
import { TokenPayload } from '../dto/auth.dto';
|
||||
declare global {
|
||||
namespace Express {
|
||||
interface Request {
|
||||
user?: TokenPayload;
|
||||
tenantId?: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
export declare class AuthMiddleware {
|
||||
private readonly authService;
|
||||
private readonly dataSource;
|
||||
constructor(authService: AuthService, dataSource: DataSource);
|
||||
/**
|
||||
* Middleware de autenticación requerida
|
||||
*/
|
||||
authenticate: (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
||||
/**
|
||||
* Middleware de autenticación opcional
|
||||
*/
|
||||
optionalAuthenticate: (req: Request, _res: Response, next: NextFunction) => Promise<void>;
|
||||
/**
|
||||
* Middleware de autorización por roles
|
||||
*/
|
||||
authorize: (...allowedRoles: string[]) => (req: Request, res: Response, next: NextFunction) => void;
|
||||
/**
|
||||
* Middleware que requiere rol de admin
|
||||
*/
|
||||
requireAdmin: (req: Request, res: Response, next: NextFunction) => void;
|
||||
/**
|
||||
* Middleware que requiere ser supervisor
|
||||
*/
|
||||
requireSupervisor: (req: Request, res: Response, next: NextFunction) => void;
|
||||
/**
|
||||
* Extraer token del header Authorization
|
||||
*/
|
||||
private extractToken;
|
||||
/**
|
||||
* Configurar contexto de tenant para RLS
|
||||
*/
|
||||
private setTenantContext;
|
||||
}
|
||||
/**
|
||||
* Factory para crear middleware de autenticación
|
||||
*/
|
||||
export declare function createAuthMiddleware(authService: AuthService, dataSource: DataSource): AuthMiddleware;
|
||||
//# sourceMappingURL=auth.middleware.d.ts.map
|
||||
1
dist/modules/auth/middleware/auth.middleware.d.ts.map
vendored
Normal file
1
dist/modules/auth/middleware/auth.middleware.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.middleware.d.ts","sourceRoot":"","sources":["../../../../src/modules/auth/middleware/auth.middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,IAAI,CAAC,EAAE,YAAY,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;SACnB;KACF;CACF;AAED,qBAAa,cAAc;IAEvB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,UAAU;gBADV,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,UAAU;IAGzC;;OAEG;IACH,YAAY,GAAU,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAoCnF;IAEF;;OAEG;IACH,oBAAoB,GAAU,KAAK,OAAO,EAAE,MAAM,QAAQ,EAAE,MAAM,YAAY,KAAG,OAAO,CAAC,IAAI,CAAC,CAmB5F;IAEF;;OAEG;IACH,SAAS,GAAI,GAAG,cAAc,MAAM,EAAE,MAC5B,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAqB9D;IAEF;;OAEG;IACH,YAAY,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAEpE;IAEF;;OAEG;IACH,iBAAiB,GAAI,KAAK,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,KAAG,IAAI,CAEzE;IAEF;;OAEG;IACH,OAAO,CAAC,YAAY;IAiBpB;;OAEG;YACW,gBAAgB;CAQ/B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,UAAU,GACrB,cAAc,CAEhB"}
|
||||
146
dist/modules/auth/middleware/auth.middleware.js
vendored
Normal file
146
dist/modules/auth/middleware/auth.middleware.js
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Auth Middleware - Middleware de Autenticación
|
||||
*
|
||||
* Middleware para Express que valida JWT y extrae información del usuario.
|
||||
* Configura el tenant_id para RLS en PostgreSQL.
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthMiddleware = void 0;
|
||||
exports.createAuthMiddleware = createAuthMiddleware;
|
||||
class AuthMiddleware {
|
||||
authService;
|
||||
dataSource;
|
||||
constructor(authService, dataSource) {
|
||||
this.authService = authService;
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
/**
|
||||
* Middleware de autenticación requerida
|
||||
*/
|
||||
authenticate = async (req, res, next) => {
|
||||
try {
|
||||
const token = this.extractToken(req);
|
||||
if (!token) {
|
||||
res.status(401).json({
|
||||
error: 'Unauthorized',
|
||||
message: 'No token provided',
|
||||
});
|
||||
return;
|
||||
}
|
||||
const validation = this.authService.validateAccessToken(token);
|
||||
if (!validation.valid || !validation.payload) {
|
||||
res.status(401).json({
|
||||
error: 'Unauthorized',
|
||||
message: validation.error || 'Invalid token',
|
||||
});
|
||||
return;
|
||||
}
|
||||
// Establecer información en el request
|
||||
req.user = validation.payload;
|
||||
req.tenantId = validation.payload.tenantId;
|
||||
// Configurar tenant_id para RLS en PostgreSQL
|
||||
await this.setTenantContext(validation.payload.tenantId);
|
||||
next();
|
||||
}
|
||||
catch (error) {
|
||||
res.status(401).json({
|
||||
error: 'Unauthorized',
|
||||
message: 'Authentication failed',
|
||||
});
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Middleware de autenticación opcional
|
||||
*/
|
||||
optionalAuthenticate = async (req, _res, next) => {
|
||||
try {
|
||||
const token = this.extractToken(req);
|
||||
if (token) {
|
||||
const validation = this.authService.validateAccessToken(token);
|
||||
if (validation.valid && validation.payload) {
|
||||
req.user = validation.payload;
|
||||
req.tenantId = validation.payload.tenantId;
|
||||
await this.setTenantContext(validation.payload.tenantId);
|
||||
}
|
||||
}
|
||||
next();
|
||||
}
|
||||
catch {
|
||||
// Si hay error, continuar sin autenticación
|
||||
next();
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Middleware de autorización por roles
|
||||
*/
|
||||
authorize = (...allowedRoles) => {
|
||||
return (req, res, next) => {
|
||||
if (!req.user) {
|
||||
res.status(401).json({
|
||||
error: 'Unauthorized',
|
||||
message: 'Authentication required',
|
||||
});
|
||||
return;
|
||||
}
|
||||
const hasRole = req.user.roles.some((role) => allowedRoles.includes(role));
|
||||
if (!hasRole) {
|
||||
res.status(403).json({
|
||||
error: 'Forbidden',
|
||||
message: 'Insufficient permissions',
|
||||
});
|
||||
return;
|
||||
}
|
||||
next();
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Middleware que requiere rol de admin
|
||||
*/
|
||||
requireAdmin = (req, res, next) => {
|
||||
return this.authorize('admin', 'super_admin')(req, res, next);
|
||||
};
|
||||
/**
|
||||
* Middleware que requiere ser supervisor
|
||||
*/
|
||||
requireSupervisor = (req, res, next) => {
|
||||
return this.authorize('admin', 'super_admin', 'supervisor_obra', 'supervisor_hse')(req, res, next);
|
||||
};
|
||||
/**
|
||||
* Extraer token del header Authorization
|
||||
*/
|
||||
extractToken(req) {
|
||||
const authHeader = req.headers.authorization;
|
||||
if (!authHeader) {
|
||||
return null;
|
||||
}
|
||||
// Bearer token
|
||||
const [type, token] = authHeader.split(' ');
|
||||
if (type !== 'Bearer' || !token) {
|
||||
return null;
|
||||
}
|
||||
return token;
|
||||
}
|
||||
/**
|
||||
* Configurar contexto de tenant para RLS
|
||||
*/
|
||||
async setTenantContext(tenantId) {
|
||||
try {
|
||||
await this.dataSource.query(`SET app.current_tenant_id = '${tenantId}'`);
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error setting tenant context:', error);
|
||||
throw new Error('Failed to set tenant context');
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.AuthMiddleware = AuthMiddleware;
|
||||
/**
|
||||
* Factory para crear middleware de autenticación
|
||||
*/
|
||||
function createAuthMiddleware(authService, dataSource) {
|
||||
return new AuthMiddleware(authService, dataSource);
|
||||
}
|
||||
//# sourceMappingURL=auth.middleware.js.map
|
||||
1
dist/modules/auth/middleware/auth.middleware.js.map
vendored
Normal file
1
dist/modules/auth/middleware/auth.middleware.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.middleware.js","sourceRoot":"","sources":["../../../../src/modules/auth/middleware/auth.middleware.ts"],"names":[],"mappings":"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"}
|
||||
69
dist/modules/auth/services/auth.service.d.ts
vendored
Normal file
69
dist/modules/auth/services/auth.service.d.ts
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* AuthService - Servicio de Autenticación
|
||||
*
|
||||
* Gestiona login, logout, refresh tokens y validación de JWT.
|
||||
* Implementa patrón multi-tenant con verificación de tenant_id.
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
import { Repository } from 'typeorm';
|
||||
import { User } from '../../core/entities/user.entity';
|
||||
import { Tenant } from '../../core/entities/tenant.entity';
|
||||
import { LoginDto, RegisterDto, RefreshTokenDto, ChangePasswordDto, AuthResponse, TokenValidationResult } from '../dto/auth.dto';
|
||||
export interface RefreshToken {
|
||||
id: string;
|
||||
userId: string;
|
||||
token: string;
|
||||
expiresAt: Date;
|
||||
revokedAt?: Date;
|
||||
}
|
||||
export declare class AuthService {
|
||||
private readonly userRepository;
|
||||
private readonly tenantRepository;
|
||||
private readonly refreshTokenRepository;
|
||||
private readonly jwtSecret;
|
||||
private readonly jwtExpiresIn;
|
||||
private readonly jwtRefreshExpiresIn;
|
||||
constructor(userRepository: Repository<User>, tenantRepository: Repository<Tenant>, refreshTokenRepository: Repository<RefreshToken>);
|
||||
/**
|
||||
* Login de usuario
|
||||
*/
|
||||
login(dto: LoginDto): Promise<AuthResponse>;
|
||||
/**
|
||||
* Registro de usuario
|
||||
*/
|
||||
register(dto: RegisterDto): Promise<AuthResponse>;
|
||||
/**
|
||||
* Refresh de token
|
||||
*/
|
||||
refresh(dto: RefreshTokenDto): Promise<AuthResponse>;
|
||||
/**
|
||||
* Logout - Revocar refresh token
|
||||
*/
|
||||
logout(refreshToken: string): Promise<void>;
|
||||
/**
|
||||
* Cambiar password
|
||||
*/
|
||||
changePassword(userId: string, dto: ChangePasswordDto): Promise<void>;
|
||||
/**
|
||||
* Validar access token
|
||||
*/
|
||||
validateAccessToken(token: string): TokenValidationResult;
|
||||
/**
|
||||
* Validar token
|
||||
*/
|
||||
private validateToken;
|
||||
/**
|
||||
* Generar access token
|
||||
*/
|
||||
private generateAccessToken;
|
||||
/**
|
||||
* Generar refresh token
|
||||
*/
|
||||
private generateRefreshToken;
|
||||
/**
|
||||
* Convertir expiresIn a segundos
|
||||
*/
|
||||
private getExpiresInSeconds;
|
||||
}
|
||||
//# sourceMappingURL=auth.service.d.ts.map
|
||||
1
dist/modules/auth/services/auth.service.d.ts.map
vendored
Normal file
1
dist/modules/auth/services/auth.service.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.service.d.ts","sourceRoot":"","sources":["../../../../src/modules/auth/services/auth.service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAC3D,OAAO,EACL,QAAQ,EACR,WAAW,EACX,eAAe,EACf,iBAAiB,EAEjB,YAAY,EACZ,qBAAqB,EACtB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB;AAED,qBAAa,WAAW;IAMpB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,sBAAsB;IAPzC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;gBAG1B,cAAc,EAAE,UAAU,CAAC,IAAI,CAAC,EAChC,gBAAgB,EAAE,UAAU,CAAC,MAAM,CAAC,EACpC,sBAAsB,EAAE,UAAU,CAAC,YAAY,CAAC;IAOnE;;OAEG;IACG,KAAK,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IAgEjD;;OAEG;IACG,QAAQ,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAyDvD;;OAEG;IACG,OAAO,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC;IA8D1D;;OAEG;IACG,MAAM,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD;;OAEG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB3E;;OAEG;IACH,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,qBAAqB;IAIzD;;OAEG;IACH,OAAO,CAAC,aAAa;IAoBrB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAc3B;;OAEG;YACW,oBAAoB;IAyBlC;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAe5B"}
|
||||
329
dist/modules/auth/services/auth.service.js
vendored
Normal file
329
dist/modules/auth/services/auth.service.js
vendored
Normal file
@ -0,0 +1,329 @@
|
||||
"use strict";
|
||||
/**
|
||||
* AuthService - Servicio de Autenticación
|
||||
*
|
||||
* Gestiona login, logout, refresh tokens y validación de JWT.
|
||||
* Implementa patrón multi-tenant con verificación de tenant_id.
|
||||
*
|
||||
* @module Auth
|
||||
*/
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || (function () {
|
||||
var ownKeys = function(o) {
|
||||
ownKeys = Object.getOwnPropertyNames || function (o) {
|
||||
var ar = [];
|
||||
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
||||
return ar;
|
||||
};
|
||||
return ownKeys(o);
|
||||
};
|
||||
return function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
})();
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AuthService = void 0;
|
||||
const jwt = __importStar(require("jsonwebtoken"));
|
||||
const bcrypt = __importStar(require("bcryptjs"));
|
||||
class AuthService {
|
||||
userRepository;
|
||||
tenantRepository;
|
||||
refreshTokenRepository;
|
||||
jwtSecret;
|
||||
jwtExpiresIn;
|
||||
jwtRefreshExpiresIn;
|
||||
constructor(userRepository, tenantRepository, refreshTokenRepository) {
|
||||
this.userRepository = userRepository;
|
||||
this.tenantRepository = tenantRepository;
|
||||
this.refreshTokenRepository = refreshTokenRepository;
|
||||
this.jwtSecret = process.env.JWT_SECRET || 'your-super-secret-jwt-key-change-in-production-minimum-32-chars';
|
||||
this.jwtExpiresIn = process.env.JWT_EXPIRES_IN || '1d';
|
||||
this.jwtRefreshExpiresIn = process.env.JWT_REFRESH_EXPIRES_IN || '7d';
|
||||
}
|
||||
/**
|
||||
* Login de usuario
|
||||
*/
|
||||
async login(dto) {
|
||||
// Buscar usuario por email
|
||||
const user = await this.userRepository.findOne({
|
||||
where: { email: dto.email, deletedAt: null },
|
||||
relations: ['userRoles', 'userRoles.role'],
|
||||
});
|
||||
if (!user) {
|
||||
throw new Error('Invalid credentials');
|
||||
}
|
||||
// Verificar password
|
||||
const isPasswordValid = await bcrypt.compare(dto.password, user.passwordHash);
|
||||
if (!isPasswordValid) {
|
||||
throw new Error('Invalid credentials');
|
||||
}
|
||||
// Verificar que el usuario esté activo
|
||||
if (!user.isActive) {
|
||||
throw new Error('User is not active');
|
||||
}
|
||||
// Obtener tenant
|
||||
const tenantId = dto.tenantId || user.defaultTenantId;
|
||||
if (!tenantId) {
|
||||
throw new Error('No tenant specified');
|
||||
}
|
||||
const tenant = await this.tenantRepository.findOne({
|
||||
where: { id: tenantId, isActive: true, deletedAt: null },
|
||||
});
|
||||
if (!tenant) {
|
||||
throw new Error('Tenant not found or inactive');
|
||||
}
|
||||
// Obtener roles del usuario
|
||||
const roles = user.userRoles?.map((ur) => ur.role.code) || [];
|
||||
// Generar tokens
|
||||
const accessToken = this.generateAccessToken(user, tenantId, roles);
|
||||
const refreshToken = await this.generateRefreshToken(user.id);
|
||||
// Actualizar último login
|
||||
await this.userRepository.update(user.id, { lastLoginAt: new Date() });
|
||||
return {
|
||||
accessToken,
|
||||
refreshToken,
|
||||
expiresIn: this.getExpiresInSeconds(this.jwtExpiresIn),
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
firstName: user.firstName,
|
||||
lastName: user.lastName,
|
||||
roles,
|
||||
},
|
||||
tenant: {
|
||||
id: tenant.id,
|
||||
name: tenant.name,
|
||||
},
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Registro de usuario
|
||||
*/
|
||||
async register(dto) {
|
||||
// Verificar si el email ya existe
|
||||
const existingUser = await this.userRepository.findOne({
|
||||
where: { email: dto.email },
|
||||
});
|
||||
if (existingUser) {
|
||||
throw new Error('Email already registered');
|
||||
}
|
||||
// Verificar que el tenant existe
|
||||
const tenant = await this.tenantRepository.findOne({
|
||||
where: { id: dto.tenantId, isActive: true },
|
||||
});
|
||||
if (!tenant) {
|
||||
throw new Error('Tenant not found');
|
||||
}
|
||||
// Hash del password
|
||||
const passwordHash = await bcrypt.hash(dto.password, 12);
|
||||
// Crear usuario
|
||||
const user = await this.userRepository.save(this.userRepository.create({
|
||||
email: dto.email,
|
||||
passwordHash,
|
||||
firstName: dto.firstName,
|
||||
lastName: dto.lastName,
|
||||
defaultTenantId: dto.tenantId,
|
||||
isActive: true,
|
||||
}));
|
||||
// Generar tokens (rol default: user)
|
||||
const roles = ['user'];
|
||||
const accessToken = this.generateAccessToken(user, dto.tenantId, roles);
|
||||
const refreshToken = await this.generateRefreshToken(user.id);
|
||||
return {
|
||||
accessToken,
|
||||
refreshToken,
|
||||
expiresIn: this.getExpiresInSeconds(this.jwtExpiresIn),
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
firstName: user.firstName,
|
||||
lastName: user.lastName,
|
||||
roles,
|
||||
},
|
||||
tenant: {
|
||||
id: tenant.id,
|
||||
name: tenant.name,
|
||||
},
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Refresh de token
|
||||
*/
|
||||
async refresh(dto) {
|
||||
// Validar refresh token
|
||||
const validation = this.validateToken(dto.refreshToken, 'refresh');
|
||||
if (!validation.valid || !validation.payload) {
|
||||
throw new Error('Invalid refresh token');
|
||||
}
|
||||
// Verificar que el token no está revocado
|
||||
const storedToken = await this.refreshTokenRepository.findOne({
|
||||
where: { token: dto.refreshToken, revokedAt: null },
|
||||
});
|
||||
if (!storedToken || storedToken.expiresAt < new Date()) {
|
||||
throw new Error('Refresh token expired or revoked');
|
||||
}
|
||||
// Obtener usuario
|
||||
const user = await this.userRepository.findOne({
|
||||
where: { id: validation.payload.sub, deletedAt: null },
|
||||
relations: ['userRoles', 'userRoles.role'],
|
||||
});
|
||||
if (!user || !user.isActive) {
|
||||
throw new Error('User not found or inactive');
|
||||
}
|
||||
// Obtener tenant
|
||||
const tenant = await this.tenantRepository.findOne({
|
||||
where: { id: validation.payload.tenantId, isActive: true },
|
||||
});
|
||||
if (!tenant) {
|
||||
throw new Error('Tenant not found or inactive');
|
||||
}
|
||||
const roles = user.userRoles?.map((ur) => ur.role.code) || [];
|
||||
// Revocar token anterior
|
||||
await this.refreshTokenRepository.update(storedToken.id, { revokedAt: new Date() });
|
||||
// Generar nuevos tokens
|
||||
const accessToken = this.generateAccessToken(user, tenant.id, roles);
|
||||
const refreshToken = await this.generateRefreshToken(user.id);
|
||||
return {
|
||||
accessToken,
|
||||
refreshToken,
|
||||
expiresIn: this.getExpiresInSeconds(this.jwtExpiresIn),
|
||||
user: {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
firstName: user.firstName,
|
||||
lastName: user.lastName,
|
||||
roles,
|
||||
},
|
||||
tenant: {
|
||||
id: tenant.id,
|
||||
name: tenant.name,
|
||||
},
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Logout - Revocar refresh token
|
||||
*/
|
||||
async logout(refreshToken) {
|
||||
await this.refreshTokenRepository.update({ token: refreshToken }, { revokedAt: new Date() });
|
||||
}
|
||||
/**
|
||||
* Cambiar password
|
||||
*/
|
||||
async changePassword(userId, dto) {
|
||||
const user = await this.userRepository.findOne({
|
||||
where: { id: userId },
|
||||
});
|
||||
if (!user) {
|
||||
throw new Error('User not found');
|
||||
}
|
||||
const isCurrentValid = await bcrypt.compare(dto.currentPassword, user.passwordHash);
|
||||
if (!isCurrentValid) {
|
||||
throw new Error('Current password is incorrect');
|
||||
}
|
||||
const newPasswordHash = await bcrypt.hash(dto.newPassword, 12);
|
||||
await this.userRepository.update(userId, { passwordHash: newPasswordHash });
|
||||
// Revocar todos los refresh tokens del usuario
|
||||
await this.refreshTokenRepository.update({ userId }, { revokedAt: new Date() });
|
||||
}
|
||||
/**
|
||||
* Validar access token
|
||||
*/
|
||||
validateAccessToken(token) {
|
||||
return this.validateToken(token, 'access');
|
||||
}
|
||||
/**
|
||||
* Validar token
|
||||
*/
|
||||
validateToken(token, expectedType) {
|
||||
try {
|
||||
const payload = jwt.verify(token, this.jwtSecret);
|
||||
if (payload.type !== expectedType) {
|
||||
return { valid: false, error: 'Invalid token type' };
|
||||
}
|
||||
return { valid: true, payload };
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof jwt.TokenExpiredError) {
|
||||
return { valid: false, error: 'Token expired' };
|
||||
}
|
||||
if (error instanceof jwt.JsonWebTokenError) {
|
||||
return { valid: false, error: 'Invalid token' };
|
||||
}
|
||||
return { valid: false, error: 'Token validation failed' };
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Generar access token
|
||||
*/
|
||||
generateAccessToken(user, tenantId, roles) {
|
||||
const payload = {
|
||||
sub: user.id,
|
||||
email: user.email,
|
||||
tenantId,
|
||||
roles,
|
||||
type: 'access',
|
||||
};
|
||||
return jwt.sign(payload, this.jwtSecret, {
|
||||
expiresIn: this.jwtExpiresIn,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Generar refresh token
|
||||
*/
|
||||
async generateRefreshToken(userId) {
|
||||
const payload = {
|
||||
sub: userId,
|
||||
type: 'refresh',
|
||||
};
|
||||
const token = jwt.sign(payload, this.jwtSecret, {
|
||||
expiresIn: this.jwtRefreshExpiresIn,
|
||||
});
|
||||
// Almacenar en DB
|
||||
const expiresAt = new Date();
|
||||
expiresAt.setDate(expiresAt.getDate() + 7); // 7 días
|
||||
await this.refreshTokenRepository.save(this.refreshTokenRepository.create({
|
||||
userId,
|
||||
token,
|
||||
expiresAt,
|
||||
}));
|
||||
return token;
|
||||
}
|
||||
/**
|
||||
* Convertir expiresIn a segundos
|
||||
*/
|
||||
getExpiresInSeconds(expiresIn) {
|
||||
const match = expiresIn.match(/^(\d+)([dhms])$/);
|
||||
if (!match)
|
||||
return 86400; // default 1 día
|
||||
const value = parseInt(match[1]);
|
||||
const unit = match[2];
|
||||
switch (unit) {
|
||||
case 'd': return value * 86400;
|
||||
case 'h': return value * 3600;
|
||||
case 'm': return value * 60;
|
||||
case 's': return value;
|
||||
default: return 86400;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.AuthService = AuthService;
|
||||
//# sourceMappingURL=auth.service.js.map
|
||||
1
dist/modules/auth/services/auth.service.js.map
vendored
Normal file
1
dist/modules/auth/services/auth.service.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
5
dist/modules/auth/services/index.d.ts
vendored
Normal file
5
dist/modules/auth/services/index.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Auth Module - Service Exports
|
||||
*/
|
||||
export * from './auth.service';
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
dist/modules/auth/services/index.d.ts.map
vendored
Normal file
1
dist/modules/auth/services/index.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/auth/services/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,gBAAgB,CAAC"}
|
||||
21
dist/modules/auth/services/index.js
vendored
Normal file
21
dist/modules/auth/services/index.js
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Auth Module - Service Exports
|
||||
*/
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("./auth.service"), exports);
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
dist/modules/auth/services/index.js.map
vendored
Normal file
1
dist/modules/auth/services/index.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/auth/services/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;AAEH,iDAA+B"}
|
||||
15
dist/modules/budgets/controllers/concepto.controller.d.ts
vendored
Normal file
15
dist/modules/budgets/controllers/concepto.controller.d.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* ConceptoController - Controller de conceptos de obra
|
||||
*
|
||||
* Endpoints REST para gestión del catálogo de conceptos.
|
||||
*
|
||||
* @module Budgets
|
||||
*/
|
||||
import { Router } from 'express';
|
||||
import { DataSource } from 'typeorm';
|
||||
/**
|
||||
* Crear router de conceptos
|
||||
*/
|
||||
export declare function createConceptoController(dataSource: DataSource): Router;
|
||||
export default createConceptoController;
|
||||
//# sourceMappingURL=concepto.controller.d.ts.map
|
||||
1
dist/modules/budgets/controllers/concepto.controller.d.ts.map
vendored
Normal file
1
dist/modules/budgets/controllers/concepto.controller.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"concepto.controller.d.ts","sourceRoot":"","sources":["../../../../src/modules/budgets/controllers/concepto.controller.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAUrC;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAmOvE;AAED,eAAe,wBAAwB,CAAC"}
|
||||
227
dist/modules/budgets/controllers/concepto.controller.js
vendored
Normal file
227
dist/modules/budgets/controllers/concepto.controller.js
vendored
Normal file
@ -0,0 +1,227 @@
|
||||
"use strict";
|
||||
/**
|
||||
* ConceptoController - Controller de conceptos de obra
|
||||
*
|
||||
* Endpoints REST para gestión del catálogo de conceptos.
|
||||
*
|
||||
* @module Budgets
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createConceptoController = createConceptoController;
|
||||
const express_1 = require("express");
|
||||
const concepto_service_1 = require("../services/concepto.service");
|
||||
const auth_middleware_1 = require("../../auth/middleware/auth.middleware");
|
||||
const auth_service_1 = require("../../auth/services/auth.service");
|
||||
const concepto_entity_1 = require("../entities/concepto.entity");
|
||||
const user_entity_1 = require("../../core/entities/user.entity");
|
||||
const tenant_entity_1 = require("../../core/entities/tenant.entity");
|
||||
const refresh_token_entity_1 = require("../../auth/entities/refresh-token.entity");
|
||||
/**
|
||||
* Crear router de conceptos
|
||||
*/
|
||||
function createConceptoController(dataSource) {
|
||||
const router = (0, express_1.Router)();
|
||||
// Repositorios
|
||||
const conceptoRepository = dataSource.getRepository(concepto_entity_1.Concepto);
|
||||
const userRepository = dataSource.getRepository(user_entity_1.User);
|
||||
const tenantRepository = dataSource.getRepository(tenant_entity_1.Tenant);
|
||||
const refreshTokenRepository = dataSource.getRepository(refresh_token_entity_1.RefreshToken);
|
||||
// Servicios
|
||||
const conceptoService = new concepto_service_1.ConceptoService(conceptoRepository);
|
||||
const authService = new auth_service_1.AuthService(userRepository, tenantRepository, refreshTokenRepository);
|
||||
const authMiddleware = new auth_middleware_1.AuthMiddleware(authService, dataSource);
|
||||
// Helper para crear contexto de servicio
|
||||
const getContext = (req) => {
|
||||
if (!req.tenantId) {
|
||||
throw new Error('Tenant ID is required');
|
||||
}
|
||||
return {
|
||||
tenantId: req.tenantId,
|
||||
userId: req.user?.sub,
|
||||
};
|
||||
};
|
||||
/**
|
||||
* GET /conceptos
|
||||
* Listar conceptos raíz
|
||||
*/
|
||||
router.get('/', authMiddleware.authenticate, async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const page = parseInt(req.query.page) || 1;
|
||||
const limit = Math.min(parseInt(req.query.limit) || 50, 100);
|
||||
const result = await conceptoService.findRootConceptos(getContext(req), page, limit);
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
data: result.data,
|
||||
pagination: result.meta,
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* GET /conceptos/search
|
||||
* Buscar conceptos por código o nombre
|
||||
*/
|
||||
router.get('/search', authMiddleware.authenticate, async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const term = req.query.q;
|
||||
if (!term || term.length < 2) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Search term must be at least 2 characters' });
|
||||
return;
|
||||
}
|
||||
const limit = Math.min(parseInt(req.query.limit) || 20, 50);
|
||||
const conceptos = await conceptoService.search(getContext(req), term, limit);
|
||||
res.status(200).json({ success: true, data: conceptos });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* GET /conceptos/tree
|
||||
* Obtener árbol de conceptos
|
||||
*/
|
||||
router.get('/tree', authMiddleware.authenticate, async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const rootId = req.query.rootId;
|
||||
const tree = await conceptoService.getConceptoTree(getContext(req), rootId);
|
||||
res.status(200).json({ success: true, data: tree });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* GET /conceptos/:id
|
||||
* Obtener concepto por ID
|
||||
*/
|
||||
router.get('/:id', authMiddleware.authenticate, async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const concepto = await conceptoService.findById(getContext(req), req.params.id);
|
||||
if (!concepto) {
|
||||
res.status(404).json({ error: 'Not Found', message: 'Concept not found' });
|
||||
return;
|
||||
}
|
||||
res.status(200).json({ success: true, data: concepto });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* GET /conceptos/:id/children
|
||||
* Obtener hijos de un concepto
|
||||
*/
|
||||
router.get('/:id/children', authMiddleware.authenticate, async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const children = await conceptoService.findChildren(getContext(req), req.params.id);
|
||||
res.status(200).json({ success: true, data: children });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* POST /conceptos
|
||||
* Crear concepto
|
||||
*/
|
||||
router.post('/', authMiddleware.authenticate, authMiddleware.authorize('admin', 'engineer', 'director'), async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const dto = req.body;
|
||||
if (!dto.code || !dto.name) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'code and name are required' });
|
||||
return;
|
||||
}
|
||||
// Verificar código único
|
||||
const exists = await conceptoService.codeExists(getContext(req), dto.code);
|
||||
if (exists) {
|
||||
res.status(409).json({ error: 'Conflict', message: 'Concept code already exists' });
|
||||
return;
|
||||
}
|
||||
const concepto = await conceptoService.createConcepto(getContext(req), dto);
|
||||
res.status(201).json({ success: true, data: concepto });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* PATCH /conceptos/:id
|
||||
* Actualizar concepto
|
||||
*/
|
||||
router.patch('/:id', authMiddleware.authenticate, authMiddleware.authorize('admin', 'engineer', 'director'), async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const dto = req.body;
|
||||
const concepto = await conceptoService.update(getContext(req), req.params.id, dto);
|
||||
if (!concepto) {
|
||||
res.status(404).json({ error: 'Not Found', message: 'Concept not found' });
|
||||
return;
|
||||
}
|
||||
res.status(200).json({ success: true, data: concepto });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* DELETE /conceptos/:id
|
||||
* Eliminar concepto (soft delete)
|
||||
*/
|
||||
router.delete('/:id', authMiddleware.authenticate, authMiddleware.authorize('admin', 'director'), async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const deleted = await conceptoService.softDelete(getContext(req), req.params.id);
|
||||
if (!deleted) {
|
||||
res.status(404).json({ error: 'Not Found', message: 'Concept not found' });
|
||||
return;
|
||||
}
|
||||
res.status(200).json({ success: true, message: 'Concept deleted' });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
return router;
|
||||
}
|
||||
exports.default = createConceptoController;
|
||||
//# sourceMappingURL=concepto.controller.js.map
|
||||
1
dist/modules/budgets/controllers/concepto.controller.js.map
vendored
Normal file
1
dist/modules/budgets/controllers/concepto.controller.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
7
dist/modules/budgets/controllers/index.d.ts
vendored
Normal file
7
dist/modules/budgets/controllers/index.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Budgets Controllers Index
|
||||
* @module Budgets
|
||||
*/
|
||||
export { createConceptoController } from './concepto.controller';
|
||||
export { createPresupuestoController } from './presupuesto.controller';
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
dist/modules/budgets/controllers/index.d.ts.map
vendored
Normal file
1
dist/modules/budgets/controllers/index.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/budgets/controllers/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC"}
|
||||
12
dist/modules/budgets/controllers/index.js
vendored
Normal file
12
dist/modules/budgets/controllers/index.js
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Budgets Controllers Index
|
||||
* @module Budgets
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createPresupuestoController = exports.createConceptoController = void 0;
|
||||
var concepto_controller_1 = require("./concepto.controller");
|
||||
Object.defineProperty(exports, "createConceptoController", { enumerable: true, get: function () { return concepto_controller_1.createConceptoController; } });
|
||||
var presupuesto_controller_1 = require("./presupuesto.controller");
|
||||
Object.defineProperty(exports, "createPresupuestoController", { enumerable: true, get: function () { return presupuesto_controller_1.createPresupuestoController; } });
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
dist/modules/budgets/controllers/index.js.map
vendored
Normal file
1
dist/modules/budgets/controllers/index.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/budgets/controllers/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,6DAAiE;AAAxD,+HAAA,wBAAwB,OAAA;AACjC,mEAAuE;AAA9D,qIAAA,2BAA2B,OAAA"}
|
||||
15
dist/modules/budgets/controllers/presupuesto.controller.d.ts
vendored
Normal file
15
dist/modules/budgets/controllers/presupuesto.controller.d.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* PresupuestoController - Controller de presupuestos
|
||||
*
|
||||
* Endpoints REST para gestión de presupuestos de obra.
|
||||
*
|
||||
* @module Budgets
|
||||
*/
|
||||
import { Router } from 'express';
|
||||
import { DataSource } from 'typeorm';
|
||||
/**
|
||||
* Crear router de presupuestos
|
||||
*/
|
||||
export declare function createPresupuestoController(dataSource: DataSource): Router;
|
||||
export default createPresupuestoController;
|
||||
//# sourceMappingURL=presupuesto.controller.d.ts.map
|
||||
1
dist/modules/budgets/controllers/presupuesto.controller.d.ts.map
vendored
Normal file
1
dist/modules/budgets/controllers/presupuesto.controller.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"presupuesto.controller.d.ts","sourceRoot":"","sources":["../../../../src/modules/budgets/controllers/presupuesto.controller.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAWrC;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAqQ1E;AAED,eAAe,2BAA2B,CAAC"}
|
||||
262
dist/modules/budgets/controllers/presupuesto.controller.js
vendored
Normal file
262
dist/modules/budgets/controllers/presupuesto.controller.js
vendored
Normal file
@ -0,0 +1,262 @@
|
||||
"use strict";
|
||||
/**
|
||||
* PresupuestoController - Controller de presupuestos
|
||||
*
|
||||
* Endpoints REST para gestión de presupuestos de obra.
|
||||
*
|
||||
* @module Budgets
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createPresupuestoController = createPresupuestoController;
|
||||
const express_1 = require("express");
|
||||
const presupuesto_service_1 = require("../services/presupuesto.service");
|
||||
const auth_middleware_1 = require("../../auth/middleware/auth.middleware");
|
||||
const auth_service_1 = require("../../auth/services/auth.service");
|
||||
const presupuesto_entity_1 = require("../entities/presupuesto.entity");
|
||||
const presupuesto_partida_entity_1 = require("../entities/presupuesto-partida.entity");
|
||||
const user_entity_1 = require("../../core/entities/user.entity");
|
||||
const tenant_entity_1 = require("../../core/entities/tenant.entity");
|
||||
const refresh_token_entity_1 = require("../../auth/entities/refresh-token.entity");
|
||||
/**
|
||||
* Crear router de presupuestos
|
||||
*/
|
||||
function createPresupuestoController(dataSource) {
|
||||
const router = (0, express_1.Router)();
|
||||
// Repositorios
|
||||
const presupuestoRepository = dataSource.getRepository(presupuesto_entity_1.Presupuesto);
|
||||
const partidaRepository = dataSource.getRepository(presupuesto_partida_entity_1.PresupuestoPartida);
|
||||
const userRepository = dataSource.getRepository(user_entity_1.User);
|
||||
const tenantRepository = dataSource.getRepository(tenant_entity_1.Tenant);
|
||||
const refreshTokenRepository = dataSource.getRepository(refresh_token_entity_1.RefreshToken);
|
||||
// Servicios
|
||||
const presupuestoService = new presupuesto_service_1.PresupuestoService(presupuestoRepository, partidaRepository);
|
||||
const authService = new auth_service_1.AuthService(userRepository, tenantRepository, refreshTokenRepository);
|
||||
const authMiddleware = new auth_middleware_1.AuthMiddleware(authService, dataSource);
|
||||
// Helper para crear contexto de servicio
|
||||
const getContext = (req) => {
|
||||
if (!req.tenantId) {
|
||||
throw new Error('Tenant ID is required');
|
||||
}
|
||||
return {
|
||||
tenantId: req.tenantId,
|
||||
userId: req.user?.sub,
|
||||
};
|
||||
};
|
||||
/**
|
||||
* GET /presupuestos
|
||||
* Listar presupuestos
|
||||
*/
|
||||
router.get('/', authMiddleware.authenticate, async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const page = parseInt(req.query.page) || 1;
|
||||
const limit = Math.min(parseInt(req.query.limit) || 20, 100);
|
||||
const fraccionamientoId = req.query.fraccionamientoId;
|
||||
let result;
|
||||
if (fraccionamientoId) {
|
||||
result = await presupuestoService.findByFraccionamiento(getContext(req), fraccionamientoId, page, limit);
|
||||
}
|
||||
else {
|
||||
result = await presupuestoService.findAll(getContext(req), { page, limit });
|
||||
}
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
data: result.data,
|
||||
pagination: result.meta,
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* GET /presupuestos/:id
|
||||
* Obtener presupuesto por ID con sus partidas
|
||||
*/
|
||||
router.get('/:id', authMiddleware.authenticate, async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const presupuesto = await presupuestoService.findWithPartidas(getContext(req), req.params.id);
|
||||
if (!presupuesto) {
|
||||
res.status(404).json({ error: 'Not Found', message: 'Budget not found' });
|
||||
return;
|
||||
}
|
||||
res.status(200).json({ success: true, data: presupuesto });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* POST /presupuestos
|
||||
* Crear presupuesto
|
||||
*/
|
||||
router.post('/', authMiddleware.authenticate, authMiddleware.authorize('admin', 'engineer', 'director'), async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const dto = req.body;
|
||||
if (!dto.code || !dto.name) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'code and name are required' });
|
||||
return;
|
||||
}
|
||||
const presupuesto = await presupuestoService.createPresupuesto(getContext(req), dto);
|
||||
res.status(201).json({ success: true, data: presupuesto });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* POST /presupuestos/:id/partidas
|
||||
* Agregar partida al presupuesto
|
||||
*/
|
||||
router.post('/:id/partidas', authMiddleware.authenticate, authMiddleware.authorize('admin', 'engineer', 'director'), async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const dto = req.body;
|
||||
if (!dto.conceptoId || dto.quantity === undefined || dto.unitPrice === undefined) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'conceptoId, quantity and unitPrice are required' });
|
||||
return;
|
||||
}
|
||||
const partida = await presupuestoService.addPartida(getContext(req), req.params.id, dto);
|
||||
res.status(201).json({ success: true, data: partida });
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof Error && error.message === 'Presupuesto not found') {
|
||||
res.status(404).json({ error: 'Not Found', message: error.message });
|
||||
return;
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* PATCH /presupuestos/:id/partidas/:partidaId
|
||||
* Actualizar partida
|
||||
*/
|
||||
router.patch('/:id/partidas/:partidaId', authMiddleware.authenticate, authMiddleware.authorize('admin', 'engineer', 'director'), async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const dto = req.body;
|
||||
const partida = await presupuestoService.updatePartida(getContext(req), req.params.partidaId, dto);
|
||||
if (!partida) {
|
||||
res.status(404).json({ error: 'Not Found', message: 'Budget item not found' });
|
||||
return;
|
||||
}
|
||||
res.status(200).json({ success: true, data: partida });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* DELETE /presupuestos/:id/partidas/:partidaId
|
||||
* Eliminar partida
|
||||
*/
|
||||
router.delete('/:id/partidas/:partidaId', authMiddleware.authenticate, authMiddleware.authorize('admin', 'engineer', 'director'), async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const deleted = await presupuestoService.removePartida(getContext(req), req.params.partidaId);
|
||||
if (!deleted) {
|
||||
res.status(404).json({ error: 'Not Found', message: 'Budget item not found' });
|
||||
return;
|
||||
}
|
||||
res.status(200).json({ success: true, message: 'Budget item deleted' });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* POST /presupuestos/:id/version
|
||||
* Crear nueva versión del presupuesto
|
||||
*/
|
||||
router.post('/:id/version', authMiddleware.authenticate, authMiddleware.authorize('admin', 'director'), async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const newVersion = await presupuestoService.createNewVersion(getContext(req), req.params.id);
|
||||
res.status(201).json({ success: true, data: newVersion });
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof Error && error.message === 'Presupuesto not found') {
|
||||
res.status(404).json({ error: 'Not Found', message: error.message });
|
||||
return;
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* POST /presupuestos/:id/approve
|
||||
* Aprobar presupuesto
|
||||
*/
|
||||
router.post('/:id/approve', authMiddleware.authenticate, authMiddleware.authorize('admin', 'director'), async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const presupuesto = await presupuestoService.approve(getContext(req), req.params.id);
|
||||
if (!presupuesto) {
|
||||
res.status(404).json({ error: 'Not Found', message: 'Budget not found' });
|
||||
return;
|
||||
}
|
||||
res.status(200).json({ success: true, data: presupuesto, message: 'Budget approved' });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* DELETE /presupuestos/:id
|
||||
* Eliminar presupuesto (soft delete)
|
||||
*/
|
||||
router.delete('/:id', authMiddleware.authenticate, authMiddleware.authorize('admin', 'director'), async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const deleted = await presupuestoService.softDelete(getContext(req), req.params.id);
|
||||
if (!deleted) {
|
||||
res.status(404).json({ error: 'Not Found', message: 'Budget not found' });
|
||||
return;
|
||||
}
|
||||
res.status(200).json({ success: true, message: 'Budget deleted' });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
return router;
|
||||
}
|
||||
exports.default = createPresupuestoController;
|
||||
//# sourceMappingURL=presupuesto.controller.js.map
|
||||
1
dist/modules/budgets/controllers/presupuesto.controller.js.map
vendored
Normal file
1
dist/modules/budgets/controllers/presupuesto.controller.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
35
dist/modules/budgets/entities/concepto.entity.d.ts
vendored
Normal file
35
dist/modules/budgets/entities/concepto.entity.d.ts
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Concepto Entity
|
||||
* Catalogo de conceptos de obra (estructura jerarquica)
|
||||
*
|
||||
* @module Budgets
|
||||
* @table construction.conceptos
|
||||
* @ddl schemas/01-construction-schema-ddl.sql
|
||||
*/
|
||||
import { Tenant } from '../../core/entities/tenant.entity';
|
||||
import { User } from '../../core/entities/user.entity';
|
||||
export declare class Concepto {
|
||||
id: string;
|
||||
tenantId: string;
|
||||
parentId: string | null;
|
||||
code: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
unitId: string | null;
|
||||
unitPrice: number | null;
|
||||
isComposite: boolean;
|
||||
level: number;
|
||||
path: string | null;
|
||||
createdAt: Date;
|
||||
createdById: string | null;
|
||||
updatedAt: Date | null;
|
||||
updatedById: string | null;
|
||||
deletedAt: Date | null;
|
||||
deletedById: string | null;
|
||||
tenant: Tenant;
|
||||
parent: Concepto | null;
|
||||
children: Concepto[];
|
||||
createdBy: User | null;
|
||||
updatedBy: User | null;
|
||||
}
|
||||
//# sourceMappingURL=concepto.entity.d.ts.map
|
||||
1
dist/modules/budgets/entities/concepto.entity.d.ts.map
vendored
Normal file
1
dist/modules/budgets/entities/concepto.entity.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"concepto.entity.d.ts","sourceRoot":"","sources":["../../../../src/modules/budgets/entities/concepto.entity.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AAEvD,qBAKa,QAAQ;IAEnB,EAAE,EAAE,MAAM,CAAC;IAGX,QAAQ,EAAE,MAAM,CAAC;IAGjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IAGxB,IAAI,EAAE,MAAM,CAAC;IAGb,IAAI,EAAE,MAAM,CAAC;IAGb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAG3B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAGtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAGzB,WAAW,EAAE,OAAO,CAAC;IAGrB,KAAK,EAAE,MAAM,CAAC;IAGd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAGpB,SAAS,EAAE,IAAI,CAAC;IAGhB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAG3B,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IAGvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAG3B,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IAGvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAK3B,MAAM,EAAE,MAAM,CAAC;IAIf,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IAGxB,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAIrB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IAIvB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;CACxB"}
|
||||
149
dist/modules/budgets/entities/concepto.entity.js
vendored
Normal file
149
dist/modules/budgets/entities/concepto.entity.js
vendored
Normal file
@ -0,0 +1,149 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Concepto Entity
|
||||
* Catalogo de conceptos de obra (estructura jerarquica)
|
||||
*
|
||||
* @module Budgets
|
||||
* @table construction.conceptos
|
||||
* @ddl schemas/01-construction-schema-ddl.sql
|
||||
*/
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Concepto = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
const tenant_entity_1 = require("../../core/entities/tenant.entity");
|
||||
const user_entity_1 = require("../../core/entities/user.entity");
|
||||
let Concepto = class Concepto {
|
||||
id;
|
||||
tenantId;
|
||||
parentId;
|
||||
code;
|
||||
name;
|
||||
description;
|
||||
unitId;
|
||||
unitPrice;
|
||||
isComposite;
|
||||
level;
|
||||
path;
|
||||
createdAt;
|
||||
createdById;
|
||||
updatedAt;
|
||||
updatedById;
|
||||
deletedAt;
|
||||
deletedById;
|
||||
// Relations
|
||||
tenant;
|
||||
parent;
|
||||
children;
|
||||
createdBy;
|
||||
updatedBy;
|
||||
};
|
||||
exports.Concepto = Concepto;
|
||||
__decorate([
|
||||
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
||||
__metadata("design:type", String)
|
||||
], Concepto.prototype, "id", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'tenant_id', type: 'uuid' }),
|
||||
__metadata("design:type", String)
|
||||
], Concepto.prototype, "tenantId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'parent_id', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Concepto.prototype, "parentId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'varchar', length: 50 }),
|
||||
__metadata("design:type", String)
|
||||
], Concepto.prototype, "code", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'varchar', length: 255 }),
|
||||
__metadata("design:type", String)
|
||||
], Concepto.prototype, "name", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'text', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Concepto.prototype, "description", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'unit_id', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Concepto.prototype, "unitId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'unit_price', type: 'decimal', precision: 12, scale: 4, nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Concepto.prototype, "unitPrice", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'is_composite', type: 'boolean', default: false }),
|
||||
__metadata("design:type", Boolean)
|
||||
], Concepto.prototype, "isComposite", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'integer', default: 0 }),
|
||||
__metadata("design:type", Number)
|
||||
], Concepto.prototype, "level", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'varchar', length: 500, nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Concepto.prototype, "path", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.CreateDateColumn)({ name: 'created_at', type: 'timestamptz' }),
|
||||
__metadata("design:type", Date)
|
||||
], Concepto.prototype, "createdAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'created_by', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Concepto.prototype, "createdById", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.UpdateDateColumn)({ name: 'updated_at', type: 'timestamptz', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Concepto.prototype, "updatedAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'updated_by', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Concepto.prototype, "updatedById", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'deleted_at', type: 'timestamptz', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Concepto.prototype, "deletedAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'deleted_by', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Concepto.prototype, "deletedById", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => tenant_entity_1.Tenant),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'tenant_id' }),
|
||||
__metadata("design:type", tenant_entity_1.Tenant)
|
||||
], Concepto.prototype, "tenant", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => Concepto, (c) => c.children, { nullable: true }),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'parent_id' }),
|
||||
__metadata("design:type", Object)
|
||||
], Concepto.prototype, "parent", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.OneToMany)(() => Concepto, (c) => c.parent),
|
||||
__metadata("design:type", Array)
|
||||
], Concepto.prototype, "children", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => user_entity_1.User),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'created_by' }),
|
||||
__metadata("design:type", Object)
|
||||
], Concepto.prototype, "createdBy", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => user_entity_1.User),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'updated_by' }),
|
||||
__metadata("design:type", Object)
|
||||
], Concepto.prototype, "updatedBy", void 0);
|
||||
exports.Concepto = Concepto = __decorate([
|
||||
(0, typeorm_1.Entity)({ schema: 'construction', name: 'conceptos' }),
|
||||
(0, typeorm_1.Index)(['tenantId', 'code'], { unique: true }),
|
||||
(0, typeorm_1.Index)(['tenantId']),
|
||||
(0, typeorm_1.Index)(['parentId']),
|
||||
(0, typeorm_1.Index)(['code'])
|
||||
], Concepto);
|
||||
//# sourceMappingURL=concepto.entity.js.map
|
||||
1
dist/modules/budgets/entities/concepto.entity.js.map
vendored
Normal file
1
dist/modules/budgets/entities/concepto.entity.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"concepto.entity.js","sourceRoot":"","sources":["../../../../src/modules/budgets/entities/concepto.entity.ts"],"names":[],"mappings":"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"}
|
||||
8
dist/modules/budgets/entities/index.d.ts
vendored
Normal file
8
dist/modules/budgets/entities/index.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Budgets Module - Entity Exports
|
||||
* MAI-003: Presupuestos
|
||||
*/
|
||||
export * from './concepto.entity';
|
||||
export * from './presupuesto.entity';
|
||||
export * from './presupuesto-partida.entity';
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
dist/modules/budgets/entities/index.d.ts.map
vendored
Normal file
1
dist/modules/budgets/entities/index.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/budgets/entities/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,8BAA8B,CAAC"}
|
||||
24
dist/modules/budgets/entities/index.js
vendored
Normal file
24
dist/modules/budgets/entities/index.js
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Budgets Module - Entity Exports
|
||||
* MAI-003: Presupuestos
|
||||
*/
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("./concepto.entity"), exports);
|
||||
__exportStar(require("./presupuesto.entity"), exports);
|
||||
__exportStar(require("./presupuesto-partida.entity"), exports);
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
dist/modules/budgets/entities/index.js.map
vendored
Normal file
1
dist/modules/budgets/entities/index.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/budgets/entities/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;AAEH,oDAAkC;AAClC,uDAAqC;AACrC,+DAA6C"}
|
||||
33
dist/modules/budgets/entities/presupuesto-partida.entity.d.ts
vendored
Normal file
33
dist/modules/budgets/entities/presupuesto-partida.entity.d.ts
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/**
|
||||
* PresupuestoPartida Entity
|
||||
* Lineas/partidas de un presupuesto
|
||||
*
|
||||
* @module Budgets
|
||||
* @table construction.presupuesto_partidas
|
||||
* @ddl schemas/01-construction-schema-ddl.sql
|
||||
*/
|
||||
import { Tenant } from '../../core/entities/tenant.entity';
|
||||
import { User } from '../../core/entities/user.entity';
|
||||
import { Presupuesto } from './presupuesto.entity';
|
||||
import { Concepto } from './concepto.entity';
|
||||
export declare class PresupuestoPartida {
|
||||
id: string;
|
||||
tenantId: string;
|
||||
presupuestoId: string;
|
||||
conceptoId: string;
|
||||
sequence: number;
|
||||
quantity: number;
|
||||
unitPrice: number;
|
||||
totalAmount: number;
|
||||
createdAt: Date;
|
||||
createdById: string | null;
|
||||
updatedAt: Date | null;
|
||||
updatedById: string | null;
|
||||
deletedAt: Date | null;
|
||||
deletedById: string | null;
|
||||
tenant: Tenant;
|
||||
presupuesto: Presupuesto;
|
||||
concepto: Concepto;
|
||||
createdBy: User | null;
|
||||
}
|
||||
//# sourceMappingURL=presupuesto-partida.entity.d.ts.map
|
||||
1
dist/modules/budgets/entities/presupuesto-partida.entity.d.ts.map
vendored
Normal file
1
dist/modules/budgets/entities/presupuesto-partida.entity.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"presupuesto-partida.entity.d.ts","sourceRoot":"","sources":["../../../../src/modules/budgets/entities/presupuesto-partida.entity.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,qBAGa,kBAAkB;IAE7B,EAAE,EAAE,MAAM,CAAC;IAGX,QAAQ,EAAE,MAAM,CAAC;IAGjB,aAAa,EAAE,MAAM,CAAC;IAGtB,UAAU,EAAE,MAAM,CAAC;IAGnB,QAAQ,EAAE,MAAM,CAAC;IAGjB,QAAQ,EAAE,MAAM,CAAC;IAGjB,SAAS,EAAE,MAAM,CAAC;IAWlB,WAAW,EAAE,MAAM,CAAC;IAGpB,SAAS,EAAE,IAAI,CAAC;IAGhB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAG3B,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IAGvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAG3B,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IAGvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAK3B,MAAM,EAAE,MAAM,CAAC;IAIf,WAAW,EAAE,WAAW,CAAC;IAIzB,QAAQ,EAAE,QAAQ,CAAC;IAInB,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;CACxB"}
|
||||
137
dist/modules/budgets/entities/presupuesto-partida.entity.js
vendored
Normal file
137
dist/modules/budgets/entities/presupuesto-partida.entity.js
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
"use strict";
|
||||
/**
|
||||
* PresupuestoPartida Entity
|
||||
* Lineas/partidas de un presupuesto
|
||||
*
|
||||
* @module Budgets
|
||||
* @table construction.presupuesto_partidas
|
||||
* @ddl schemas/01-construction-schema-ddl.sql
|
||||
*/
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.PresupuestoPartida = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
const tenant_entity_1 = require("../../core/entities/tenant.entity");
|
||||
const user_entity_1 = require("../../core/entities/user.entity");
|
||||
const presupuesto_entity_1 = require("./presupuesto.entity");
|
||||
const concepto_entity_1 = require("./concepto.entity");
|
||||
let PresupuestoPartida = class PresupuestoPartida {
|
||||
id;
|
||||
tenantId;
|
||||
presupuestoId;
|
||||
conceptoId;
|
||||
sequence;
|
||||
quantity;
|
||||
unitPrice;
|
||||
// Columna calculada (GENERATED ALWAYS AS) - solo lectura
|
||||
totalAmount;
|
||||
createdAt;
|
||||
createdById;
|
||||
updatedAt;
|
||||
updatedById;
|
||||
deletedAt;
|
||||
deletedById;
|
||||
// Relations
|
||||
tenant;
|
||||
presupuesto;
|
||||
concepto;
|
||||
createdBy;
|
||||
};
|
||||
exports.PresupuestoPartida = PresupuestoPartida;
|
||||
__decorate([
|
||||
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
||||
__metadata("design:type", String)
|
||||
], PresupuestoPartida.prototype, "id", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'tenant_id', type: 'uuid' }),
|
||||
__metadata("design:type", String)
|
||||
], PresupuestoPartida.prototype, "tenantId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'presupuesto_id', type: 'uuid' }),
|
||||
__metadata("design:type", String)
|
||||
], PresupuestoPartida.prototype, "presupuestoId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'concepto_id', type: 'uuid' }),
|
||||
__metadata("design:type", String)
|
||||
], PresupuestoPartida.prototype, "conceptoId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'integer', default: 0 }),
|
||||
__metadata("design:type", Number)
|
||||
], PresupuestoPartida.prototype, "sequence", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'decimal', precision: 12, scale: 4, default: 0 }),
|
||||
__metadata("design:type", Number)
|
||||
], PresupuestoPartida.prototype, "quantity", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'unit_price', type: 'decimal', precision: 12, scale: 4, default: 0 }),
|
||||
__metadata("design:type", Number)
|
||||
], PresupuestoPartida.prototype, "unitPrice", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({
|
||||
name: 'total_amount',
|
||||
type: 'decimal',
|
||||
precision: 14,
|
||||
scale: 2,
|
||||
insert: false,
|
||||
update: false,
|
||||
}),
|
||||
__metadata("design:type", Number)
|
||||
], PresupuestoPartida.prototype, "totalAmount", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.CreateDateColumn)({ name: 'created_at', type: 'timestamptz' }),
|
||||
__metadata("design:type", Date)
|
||||
], PresupuestoPartida.prototype, "createdAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'created_by', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], PresupuestoPartida.prototype, "createdById", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.UpdateDateColumn)({ name: 'updated_at', type: 'timestamptz', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], PresupuestoPartida.prototype, "updatedAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'updated_by', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], PresupuestoPartida.prototype, "updatedById", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'deleted_at', type: 'timestamptz', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], PresupuestoPartida.prototype, "deletedAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'deleted_by', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], PresupuestoPartida.prototype, "deletedById", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => tenant_entity_1.Tenant),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'tenant_id' }),
|
||||
__metadata("design:type", tenant_entity_1.Tenant)
|
||||
], PresupuestoPartida.prototype, "tenant", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => presupuesto_entity_1.Presupuesto, (p) => p.partidas),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'presupuesto_id' }),
|
||||
__metadata("design:type", presupuesto_entity_1.Presupuesto)
|
||||
], PresupuestoPartida.prototype, "presupuesto", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => concepto_entity_1.Concepto),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'concepto_id' }),
|
||||
__metadata("design:type", concepto_entity_1.Concepto)
|
||||
], PresupuestoPartida.prototype, "concepto", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => user_entity_1.User),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'created_by' }),
|
||||
__metadata("design:type", Object)
|
||||
], PresupuestoPartida.prototype, "createdBy", void 0);
|
||||
exports.PresupuestoPartida = PresupuestoPartida = __decorate([
|
||||
(0, typeorm_1.Entity)({ schema: 'construction', name: 'presupuesto_partidas' }),
|
||||
(0, typeorm_1.Index)(['presupuestoId', 'conceptoId'], { unique: true }),
|
||||
(0, typeorm_1.Index)(['tenantId'])
|
||||
], PresupuestoPartida);
|
||||
//# sourceMappingURL=presupuesto-partida.entity.js.map
|
||||
1
dist/modules/budgets/entities/presupuesto-partida.entity.js.map
vendored
Normal file
1
dist/modules/budgets/entities/presupuesto-partida.entity.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"presupuesto-partida.entity.js","sourceRoot":"","sources":["../../../../src/modules/budgets/entities/presupuesto-partida.entity.ts"],"names":[],"mappings":"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"}
|
||||
39
dist/modules/budgets/entities/presupuesto.entity.d.ts
vendored
Normal file
39
dist/modules/budgets/entities/presupuesto.entity.d.ts
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Presupuesto Entity
|
||||
* Presupuestos de obra por prototipo o fraccionamiento
|
||||
*
|
||||
* @module Budgets
|
||||
* @table construction.presupuestos
|
||||
* @ddl schemas/01-construction-schema-ddl.sql
|
||||
*/
|
||||
import { Tenant } from '../../core/entities/tenant.entity';
|
||||
import { User } from '../../core/entities/user.entity';
|
||||
import { Fraccionamiento } from '../../construction/entities/fraccionamiento.entity';
|
||||
import { PresupuestoPartida } from './presupuesto-partida.entity';
|
||||
export declare class Presupuesto {
|
||||
id: string;
|
||||
tenantId: string;
|
||||
fraccionamientoId: string | null;
|
||||
prototipoId: string | null;
|
||||
code: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
version: number;
|
||||
isActive: boolean;
|
||||
totalAmount: number;
|
||||
currencyId: string | null;
|
||||
approvedAt: Date | null;
|
||||
approvedById: string | null;
|
||||
createdAt: Date;
|
||||
createdById: string | null;
|
||||
updatedAt: Date | null;
|
||||
updatedById: string | null;
|
||||
deletedAt: Date | null;
|
||||
deletedById: string | null;
|
||||
tenant: Tenant;
|
||||
fraccionamiento: Fraccionamiento | null;
|
||||
createdBy: User | null;
|
||||
approvedBy: User | null;
|
||||
partidas: PresupuestoPartida[];
|
||||
}
|
||||
//# sourceMappingURL=presupuesto.entity.d.ts.map
|
||||
1
dist/modules/budgets/entities/presupuesto.entity.d.ts.map
vendored
Normal file
1
dist/modules/budgets/entities/presupuesto.entity.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"presupuesto.entity.d.ts","sourceRoot":"","sources":["../../../../src/modules/budgets/entities/presupuesto.entity.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAE,MAAM,iCAAiC,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,oDAAoD,CAAC;AACrF,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAElE,qBAIa,WAAW;IAEtB,EAAE,EAAE,MAAM,CAAC;IAGX,QAAQ,EAAE,MAAM,CAAC;IAGjB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IAGjC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAG3B,IAAI,EAAE,MAAM,CAAC;IAGb,IAAI,EAAE,MAAM,CAAC;IAGb,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAG3B,OAAO,EAAE,MAAM,CAAC;IAGhB,QAAQ,EAAE,OAAO,CAAC;IAGlB,WAAW,EAAE,MAAM,CAAC;IAGpB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAG1B,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IAGxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAG5B,SAAS,EAAE,IAAI,CAAC;IAGhB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAG3B,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IAGvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAG3B,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IAGvB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAK3B,MAAM,EAAE,MAAM,CAAC;IAIf,eAAe,EAAE,eAAe,GAAG,IAAI,CAAC;IAIxC,SAAS,EAAE,IAAI,GAAG,IAAI,CAAC;IAIvB,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IAGxB,QAAQ,EAAE,kBAAkB,EAAE,CAAC;CAChC"}
|
||||
160
dist/modules/budgets/entities/presupuesto.entity.js
vendored
Normal file
160
dist/modules/budgets/entities/presupuesto.entity.js
vendored
Normal file
@ -0,0 +1,160 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Presupuesto Entity
|
||||
* Presupuestos de obra por prototipo o fraccionamiento
|
||||
*
|
||||
* @module Budgets
|
||||
* @table construction.presupuestos
|
||||
* @ddl schemas/01-construction-schema-ddl.sql
|
||||
*/
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Presupuesto = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
const tenant_entity_1 = require("../../core/entities/tenant.entity");
|
||||
const user_entity_1 = require("../../core/entities/user.entity");
|
||||
const fraccionamiento_entity_1 = require("../../construction/entities/fraccionamiento.entity");
|
||||
const presupuesto_partida_entity_1 = require("./presupuesto-partida.entity");
|
||||
let Presupuesto = class Presupuesto {
|
||||
id;
|
||||
tenantId;
|
||||
fraccionamientoId;
|
||||
prototipoId;
|
||||
code;
|
||||
name;
|
||||
description;
|
||||
version;
|
||||
isActive;
|
||||
totalAmount;
|
||||
currencyId;
|
||||
approvedAt;
|
||||
approvedById;
|
||||
createdAt;
|
||||
createdById;
|
||||
updatedAt;
|
||||
updatedById;
|
||||
deletedAt;
|
||||
deletedById;
|
||||
// Relations
|
||||
tenant;
|
||||
fraccionamiento;
|
||||
createdBy;
|
||||
approvedBy;
|
||||
partidas;
|
||||
};
|
||||
exports.Presupuesto = Presupuesto;
|
||||
__decorate([
|
||||
(0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
|
||||
__metadata("design:type", String)
|
||||
], Presupuesto.prototype, "id", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'tenant_id', type: 'uuid' }),
|
||||
__metadata("design:type", String)
|
||||
], Presupuesto.prototype, "tenantId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'fraccionamiento_id', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "fraccionamientoId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'prototipo_id', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "prototipoId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'varchar', length: 30 }),
|
||||
__metadata("design:type", String)
|
||||
], Presupuesto.prototype, "code", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'varchar', length: 255 }),
|
||||
__metadata("design:type", String)
|
||||
], Presupuesto.prototype, "name", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'text', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "description", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ type: 'integer', default: 1 }),
|
||||
__metadata("design:type", Number)
|
||||
], Presupuesto.prototype, "version", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'is_active', type: 'boolean', default: true }),
|
||||
__metadata("design:type", Boolean)
|
||||
], Presupuesto.prototype, "isActive", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'total_amount', type: 'decimal', precision: 16, scale: 2, default: 0 }),
|
||||
__metadata("design:type", Number)
|
||||
], Presupuesto.prototype, "totalAmount", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'currency_id', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "currencyId", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'approved_at', type: 'timestamptz', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "approvedAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'approved_by', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "approvedById", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.CreateDateColumn)({ name: 'created_at', type: 'timestamptz' }),
|
||||
__metadata("design:type", Date)
|
||||
], Presupuesto.prototype, "createdAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'created_by', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "createdById", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.UpdateDateColumn)({ name: 'updated_at', type: 'timestamptz', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "updatedAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'updated_by', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "updatedById", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'deleted_at', type: 'timestamptz', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "deletedAt", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.Column)({ name: 'deleted_by', type: 'uuid', nullable: true }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "deletedById", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => tenant_entity_1.Tenant),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'tenant_id' }),
|
||||
__metadata("design:type", tenant_entity_1.Tenant)
|
||||
], Presupuesto.prototype, "tenant", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => fraccionamiento_entity_1.Fraccionamiento, { nullable: true }),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'fraccionamiento_id' }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "fraccionamiento", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => user_entity_1.User),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'created_by' }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "createdBy", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.ManyToOne)(() => user_entity_1.User),
|
||||
(0, typeorm_1.JoinColumn)({ name: 'approved_by' }),
|
||||
__metadata("design:type", Object)
|
||||
], Presupuesto.prototype, "approvedBy", void 0);
|
||||
__decorate([
|
||||
(0, typeorm_1.OneToMany)(() => presupuesto_partida_entity_1.PresupuestoPartida, (p) => p.presupuesto),
|
||||
__metadata("design:type", Array)
|
||||
], Presupuesto.prototype, "partidas", void 0);
|
||||
exports.Presupuesto = Presupuesto = __decorate([
|
||||
(0, typeorm_1.Entity)({ schema: 'construction', name: 'presupuestos' }),
|
||||
(0, typeorm_1.Index)(['tenantId', 'code', 'version'], { unique: true }),
|
||||
(0, typeorm_1.Index)(['tenantId']),
|
||||
(0, typeorm_1.Index)(['fraccionamientoId'])
|
||||
], Presupuesto);
|
||||
//# sourceMappingURL=presupuesto.entity.js.map
|
||||
1
dist/modules/budgets/entities/presupuesto.entity.js.map
vendored
Normal file
1
dist/modules/budgets/entities/presupuesto.entity.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"presupuesto.entity.js","sourceRoot":"","sources":["../../../../src/modules/budgets/entities/presupuesto.entity.ts"],"names":[],"mappings":"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"}
|
||||
60
dist/modules/budgets/services/concepto.service.d.ts
vendored
Normal file
60
dist/modules/budgets/services/concepto.service.d.ts
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/**
|
||||
* ConceptoService - Catalogo de Conceptos de Obra
|
||||
*
|
||||
* Gestiona el catálogo jerárquico de conceptos de obra.
|
||||
* Los conceptos pueden tener estructura padre-hijo (niveles).
|
||||
*
|
||||
* @module Budgets
|
||||
*/
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseService, ServiceContext, PaginatedResult } from '../../../shared/services/base.service';
|
||||
import { Concepto } from '../entities/concepto.entity';
|
||||
export interface CreateConceptoDto {
|
||||
code: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
parentId?: string;
|
||||
unitId?: string;
|
||||
unitPrice?: number;
|
||||
isComposite?: boolean;
|
||||
}
|
||||
export interface UpdateConceptoDto {
|
||||
name?: string;
|
||||
description?: string;
|
||||
unitId?: string;
|
||||
unitPrice?: number;
|
||||
isComposite?: boolean;
|
||||
}
|
||||
export declare class ConceptoService extends BaseService<Concepto> {
|
||||
constructor(repository: Repository<Concepto>);
|
||||
/**
|
||||
* Crear un nuevo concepto con cálculo automático de nivel y path
|
||||
*/
|
||||
createConcepto(ctx: ServiceContext, data: CreateConceptoDto): Promise<Concepto>;
|
||||
/**
|
||||
* Obtener conceptos raíz (sin padre)
|
||||
*/
|
||||
findRootConceptos(ctx: ServiceContext, page?: number, limit?: number): Promise<PaginatedResult<Concepto>>;
|
||||
/**
|
||||
* Obtener hijos de un concepto
|
||||
*/
|
||||
findChildren(ctx: ServiceContext, parentId: string): Promise<Concepto[]>;
|
||||
/**
|
||||
* Obtener árbol completo de conceptos
|
||||
*/
|
||||
getConceptoTree(ctx: ServiceContext, rootId?: string): Promise<ConceptoNode[]>;
|
||||
private buildTree;
|
||||
/**
|
||||
* Buscar conceptos por código o nombre
|
||||
*/
|
||||
search(ctx: ServiceContext, term: string, limit?: number): Promise<Concepto[]>;
|
||||
/**
|
||||
* Verificar si un código ya existe
|
||||
*/
|
||||
codeExists(ctx: ServiceContext, code: string): Promise<boolean>;
|
||||
}
|
||||
interface ConceptoNode extends Concepto {
|
||||
children: ConceptoNode[];
|
||||
}
|
||||
export {};
|
||||
//# sourceMappingURL=concepto.service.d.ts.map
|
||||
1
dist/modules/budgets/services/concepto.service.d.ts.map
vendored
Normal file
1
dist/modules/budgets/services/concepto.service.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"concepto.service.d.ts","sourceRoot":"","sources":["../../../../src/modules/budgets/services/concepto.service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAU,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACrG,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAEvD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,eAAgB,SAAQ,WAAW,CAAC,QAAQ,CAAC;gBAC5C,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC;IAI5C;;OAEG;IACG,cAAc,CAClB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,QAAQ,CAAC;IAmBpB;;OAEG;IACG,iBAAiB,CACrB,GAAG,EAAE,cAAc,EACnB,IAAI,SAAI,EACR,KAAK,SAAK,GACT,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IAQrC;;OAEG;IACG,YAAY,CAChB,GAAG,EAAE,cAAc,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,QAAQ,EAAE,CAAC;IAOtB;;OAEG;IACG,eAAe,CACnB,GAAG,EAAE,cAAc,EACnB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,YAAY,EAAE,CAAC;YAaZ,SAAS;IAqBvB;;OAEG;IACG,MAAM,CACV,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,MAAM,EACZ,KAAK,SAAK,GACT,OAAO,CAAC,QAAQ,EAAE,CAAC;IAatB;;OAEG;IACG,UAAU,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAGtE;AAED,UAAU,YAAa,SAAQ,QAAQ;IACrC,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B"}
|
||||
106
dist/modules/budgets/services/concepto.service.js
vendored
Normal file
106
dist/modules/budgets/services/concepto.service.js
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
"use strict";
|
||||
/**
|
||||
* ConceptoService - Catalogo de Conceptos de Obra
|
||||
*
|
||||
* Gestiona el catálogo jerárquico de conceptos de obra.
|
||||
* Los conceptos pueden tener estructura padre-hijo (niveles).
|
||||
*
|
||||
* @module Budgets
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ConceptoService = void 0;
|
||||
const typeorm_1 = require("typeorm");
|
||||
const base_service_1 = require("../../../shared/services/base.service");
|
||||
class ConceptoService extends base_service_1.BaseService {
|
||||
constructor(repository) {
|
||||
super(repository);
|
||||
}
|
||||
/**
|
||||
* Crear un nuevo concepto con cálculo automático de nivel y path
|
||||
*/
|
||||
async createConcepto(ctx, data) {
|
||||
let level = 0;
|
||||
let path = data.code;
|
||||
if (data.parentId) {
|
||||
const parent = await this.findById(ctx, data.parentId);
|
||||
if (parent) {
|
||||
level = parent.level + 1;
|
||||
path = `${parent.path}/${data.code}`;
|
||||
}
|
||||
}
|
||||
return this.create(ctx, {
|
||||
...data,
|
||||
level,
|
||||
path,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Obtener conceptos raíz (sin padre)
|
||||
*/
|
||||
async findRootConceptos(ctx, page = 1, limit = 50) {
|
||||
return this.findAll(ctx, {
|
||||
page,
|
||||
limit,
|
||||
where: { parentId: (0, typeorm_1.IsNull)() },
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Obtener hijos de un concepto
|
||||
*/
|
||||
async findChildren(ctx, parentId) {
|
||||
return this.find(ctx, {
|
||||
where: { parentId },
|
||||
order: { code: 'ASC' },
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Obtener árbol completo de conceptos
|
||||
*/
|
||||
async getConceptoTree(ctx, rootId) {
|
||||
const where = rootId
|
||||
? { parentId: rootId }
|
||||
: { parentId: (0, typeorm_1.IsNull)() };
|
||||
const roots = await this.find(ctx, {
|
||||
where: where,
|
||||
order: { code: 'ASC' },
|
||||
});
|
||||
return this.buildTree(ctx, roots);
|
||||
}
|
||||
async buildTree(ctx, conceptos) {
|
||||
const tree = [];
|
||||
for (const concepto of conceptos) {
|
||||
const children = await this.findChildren(ctx, concepto.id);
|
||||
const childNodes = children.length > 0
|
||||
? await this.buildTree(ctx, children)
|
||||
: [];
|
||||
tree.push({
|
||||
...concepto,
|
||||
children: childNodes,
|
||||
});
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
/**
|
||||
* Buscar conceptos por código o nombre
|
||||
*/
|
||||
async search(ctx, term, limit = 20) {
|
||||
return this.repository
|
||||
.createQueryBuilder('c')
|
||||
.where('c.tenant_id = :tenantId', { tenantId: ctx.tenantId })
|
||||
.andWhere('c.deleted_at IS NULL')
|
||||
.andWhere('(c.code ILIKE :term OR c.name ILIKE :term)', {
|
||||
term: `%${term}%`,
|
||||
})
|
||||
.orderBy('c.code', 'ASC')
|
||||
.take(limit)
|
||||
.getMany();
|
||||
}
|
||||
/**
|
||||
* Verificar si un código ya existe
|
||||
*/
|
||||
async codeExists(ctx, code) {
|
||||
return this.exists(ctx, { code });
|
||||
}
|
||||
}
|
||||
exports.ConceptoService = ConceptoService;
|
||||
//# sourceMappingURL=concepto.service.js.map
|
||||
1
dist/modules/budgets/services/concepto.service.js.map
vendored
Normal file
1
dist/modules/budgets/services/concepto.service.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"concepto.service.js","sourceRoot":"","sources":["../../../../src/modules/budgets/services/concepto.service.ts"],"names":[],"mappings":"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"}
|
||||
6
dist/modules/budgets/services/index.d.ts
vendored
Normal file
6
dist/modules/budgets/services/index.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Budgets Module - Service Exports
|
||||
*/
|
||||
export * from './concepto.service';
|
||||
export * from './presupuesto.service';
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
dist/modules/budgets/services/index.d.ts.map
vendored
Normal file
1
dist/modules/budgets/services/index.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/budgets/services/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC"}
|
||||
22
dist/modules/budgets/services/index.js
vendored
Normal file
22
dist/modules/budgets/services/index.js
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Budgets Module - Service Exports
|
||||
*/
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
__exportStar(require("./concepto.service"), exports);
|
||||
__exportStar(require("./presupuesto.service"), exports);
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
dist/modules/budgets/services/index.js.map
vendored
Normal file
1
dist/modules/budgets/services/index.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/modules/budgets/services/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;AAEH,qDAAmC;AACnC,wDAAsC"}
|
||||
72
dist/modules/budgets/services/presupuesto.service.d.ts
vendored
Normal file
72
dist/modules/budgets/services/presupuesto.service.d.ts
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
/**
|
||||
* PresupuestoService - Gestión de Presupuestos de Obra
|
||||
*
|
||||
* Gestiona presupuestos de obra con sus partidas.
|
||||
* Soporta versionamiento y aprobación.
|
||||
*
|
||||
* @module Budgets
|
||||
*/
|
||||
import { Repository } from 'typeorm';
|
||||
import { BaseService, ServiceContext, PaginatedResult } from '../../../shared/services/base.service';
|
||||
import { Presupuesto } from '../entities/presupuesto.entity';
|
||||
import { PresupuestoPartida } from '../entities/presupuesto-partida.entity';
|
||||
export interface CreatePresupuestoDto {
|
||||
code: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
fraccionamientoId?: string;
|
||||
prototipoId?: string;
|
||||
currencyId?: string;
|
||||
}
|
||||
export interface AddPartidaDto {
|
||||
conceptoId: string;
|
||||
quantity: number;
|
||||
unitPrice: number;
|
||||
sequence?: number;
|
||||
}
|
||||
export interface UpdatePartidaDto {
|
||||
quantity?: number;
|
||||
unitPrice?: number;
|
||||
sequence?: number;
|
||||
}
|
||||
export declare class PresupuestoService extends BaseService<Presupuesto> {
|
||||
private readonly partidaRepository;
|
||||
constructor(repository: Repository<Presupuesto>, partidaRepository: Repository<PresupuestoPartida>);
|
||||
/**
|
||||
* Crear nuevo presupuesto
|
||||
*/
|
||||
createPresupuesto(ctx: ServiceContext, data: CreatePresupuestoDto): Promise<Presupuesto>;
|
||||
/**
|
||||
* Obtener presupuestos por fraccionamiento
|
||||
*/
|
||||
findByFraccionamiento(ctx: ServiceContext, fraccionamientoId: string, page?: number, limit?: number): Promise<PaginatedResult<Presupuesto>>;
|
||||
/**
|
||||
* Obtener presupuesto con sus partidas
|
||||
*/
|
||||
findWithPartidas(ctx: ServiceContext, id: string): Promise<Presupuesto | null>;
|
||||
/**
|
||||
* Agregar partida al presupuesto
|
||||
*/
|
||||
addPartida(ctx: ServiceContext, presupuestoId: string, data: AddPartidaDto): Promise<PresupuestoPartida>;
|
||||
/**
|
||||
* Actualizar partida
|
||||
*/
|
||||
updatePartida(ctx: ServiceContext, partidaId: string, data: UpdatePartidaDto): Promise<PresupuestoPartida | null>;
|
||||
/**
|
||||
* Eliminar partida
|
||||
*/
|
||||
removePartida(ctx: ServiceContext, partidaId: string): Promise<boolean>;
|
||||
/**
|
||||
* Recalcular total del presupuesto
|
||||
*/
|
||||
recalculateTotal(ctx: ServiceContext, presupuestoId: string): Promise<void>;
|
||||
/**
|
||||
* Crear nueva versión del presupuesto
|
||||
*/
|
||||
createNewVersion(ctx: ServiceContext, presupuestoId: string): Promise<Presupuesto>;
|
||||
/**
|
||||
* Aprobar presupuesto
|
||||
*/
|
||||
approve(ctx: ServiceContext, presupuestoId: string): Promise<Presupuesto | null>;
|
||||
}
|
||||
//# sourceMappingURL=presupuesto.service.d.ts.map
|
||||
1
dist/modules/budgets/services/presupuesto.service.d.ts.map
vendored
Normal file
1
dist/modules/budgets/services/presupuesto.service.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"presupuesto.service.d.ts","sourceRoot":"","sources":["../../../../src/modules/budgets/services/presupuesto.service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACrG,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAE5E,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,kBAAmB,SAAQ,WAAW,CAAC,WAAW,CAAC;IAG5D,OAAO,CAAC,QAAQ,CAAC,iBAAiB;gBADlC,UAAU,EAAE,UAAU,CAAC,WAAW,CAAC,EAClB,iBAAiB,EAAE,UAAU,CAAC,kBAAkB,CAAC;IAKpE;;OAEG;IACG,iBAAiB,CACrB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,WAAW,CAAC;IASvB;;OAEG;IACG,qBAAqB,CACzB,GAAG,EAAE,cAAc,EACnB,iBAAiB,EAAE,MAAM,EACzB,IAAI,SAAI,EACR,KAAK,SAAK,GACT,OAAO,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;IAQxC;;OAEG;IACG,gBAAgB,CACpB,GAAG,EAAE,cAAc,EACnB,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAW9B;;OAEG;IACG,UAAU,CACd,GAAG,EAAE,cAAc,EACnB,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,kBAAkB,CAAC;IAsB9B;;OAEG;IACG,aAAa,CACjB,GAAG,EAAE,cAAc,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAwBrC;;OAEG;IACG,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAwB7E;;OAEG;IACG,gBAAgB,CAAC,GAAG,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBjF;;OAEG;IACG,gBAAgB,CACpB,GAAG,EAAE,cAAc,EACnB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,WAAW,CAAC;IA2CvB;;OAEG;IACG,OAAO,CAAC,GAAG,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;CAWvF"}
|
||||
180
dist/modules/budgets/services/presupuesto.service.js
vendored
Normal file
180
dist/modules/budgets/services/presupuesto.service.js
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
"use strict";
|
||||
/**
|
||||
* PresupuestoService - Gestión de Presupuestos de Obra
|
||||
*
|
||||
* Gestiona presupuestos de obra con sus partidas.
|
||||
* Soporta versionamiento y aprobación.
|
||||
*
|
||||
* @module Budgets
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.PresupuestoService = void 0;
|
||||
const base_service_1 = require("../../../shared/services/base.service");
|
||||
class PresupuestoService extends base_service_1.BaseService {
|
||||
partidaRepository;
|
||||
constructor(repository, partidaRepository) {
|
||||
super(repository);
|
||||
this.partidaRepository = partidaRepository;
|
||||
}
|
||||
/**
|
||||
* Crear nuevo presupuesto
|
||||
*/
|
||||
async createPresupuesto(ctx, data) {
|
||||
return this.create(ctx, {
|
||||
...data,
|
||||
version: 1,
|
||||
isActive: true,
|
||||
totalAmount: 0,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Obtener presupuestos por fraccionamiento
|
||||
*/
|
||||
async findByFraccionamiento(ctx, fraccionamientoId, page = 1, limit = 20) {
|
||||
return this.findAll(ctx, {
|
||||
page,
|
||||
limit,
|
||||
where: { fraccionamientoId, isActive: true },
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Obtener presupuesto con sus partidas
|
||||
*/
|
||||
async findWithPartidas(ctx, id) {
|
||||
return this.repository.findOne({
|
||||
where: {
|
||||
id,
|
||||
tenantId: ctx.tenantId,
|
||||
deletedAt: null,
|
||||
},
|
||||
relations: ['partidas', 'partidas.concepto'],
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Agregar partida al presupuesto
|
||||
*/
|
||||
async addPartida(ctx, presupuestoId, data) {
|
||||
const presupuesto = await this.findById(ctx, presupuestoId);
|
||||
if (!presupuesto) {
|
||||
throw new Error('Presupuesto not found');
|
||||
}
|
||||
const partida = this.partidaRepository.create({
|
||||
tenantId: ctx.tenantId,
|
||||
presupuestoId,
|
||||
conceptoId: data.conceptoId,
|
||||
quantity: data.quantity,
|
||||
unitPrice: data.unitPrice,
|
||||
sequence: data.sequence || 0,
|
||||
createdById: ctx.userId,
|
||||
});
|
||||
const savedPartida = await this.partidaRepository.save(partida);
|
||||
await this.recalculateTotal(ctx, presupuestoId);
|
||||
return savedPartida;
|
||||
}
|
||||
/**
|
||||
* Actualizar partida
|
||||
*/
|
||||
async updatePartida(ctx, partidaId, data) {
|
||||
const partida = await this.partidaRepository.findOne({
|
||||
where: {
|
||||
id: partidaId,
|
||||
tenantId: ctx.tenantId,
|
||||
deletedAt: null,
|
||||
},
|
||||
});
|
||||
if (!partida) {
|
||||
return null;
|
||||
}
|
||||
const updated = this.partidaRepository.merge(partida, {
|
||||
...data,
|
||||
updatedById: ctx.userId,
|
||||
});
|
||||
const saved = await this.partidaRepository.save(updated);
|
||||
await this.recalculateTotal(ctx, partida.presupuestoId);
|
||||
return saved;
|
||||
}
|
||||
/**
|
||||
* Eliminar partida
|
||||
*/
|
||||
async removePartida(ctx, partidaId) {
|
||||
const partida = await this.partidaRepository.findOne({
|
||||
where: {
|
||||
id: partidaId,
|
||||
tenantId: ctx.tenantId,
|
||||
},
|
||||
});
|
||||
if (!partida) {
|
||||
return false;
|
||||
}
|
||||
await this.partidaRepository.update({ id: partidaId }, {
|
||||
deletedAt: new Date(),
|
||||
deletedById: ctx.userId,
|
||||
});
|
||||
await this.recalculateTotal(ctx, partida.presupuestoId);
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Recalcular total del presupuesto
|
||||
*/
|
||||
async recalculateTotal(ctx, presupuestoId) {
|
||||
const result = await this.partidaRepository
|
||||
.createQueryBuilder('p')
|
||||
.select('SUM(p.quantity * p.unit_price)', 'total')
|
||||
.where('p.presupuesto_id = :presupuestoId', { presupuestoId })
|
||||
.andWhere('p.deleted_at IS NULL')
|
||||
.getRawOne();
|
||||
const total = parseFloat(result?.total || '0');
|
||||
await this.repository.update({ id: presupuestoId }, { totalAmount: total, updatedById: ctx.userId });
|
||||
}
|
||||
/**
|
||||
* Crear nueva versión del presupuesto
|
||||
*/
|
||||
async createNewVersion(ctx, presupuestoId) {
|
||||
const original = await this.findWithPartidas(ctx, presupuestoId);
|
||||
if (!original) {
|
||||
throw new Error('Presupuesto not found');
|
||||
}
|
||||
// Desactivar versión anterior
|
||||
await this.repository.update({ id: presupuestoId }, { isActive: false, updatedById: ctx.userId });
|
||||
// Crear nueva versión
|
||||
const newVersion = await this.create(ctx, {
|
||||
code: original.code,
|
||||
name: original.name,
|
||||
description: original.description,
|
||||
fraccionamientoId: original.fraccionamientoId,
|
||||
prototipoId: original.prototipoId,
|
||||
currencyId: original.currencyId,
|
||||
version: original.version + 1,
|
||||
isActive: true,
|
||||
totalAmount: original.totalAmount,
|
||||
});
|
||||
// Copiar partidas
|
||||
for (const partida of original.partidas) {
|
||||
await this.partidaRepository.save(this.partidaRepository.create({
|
||||
tenantId: ctx.tenantId,
|
||||
presupuestoId: newVersion.id,
|
||||
conceptoId: partida.conceptoId,
|
||||
quantity: partida.quantity,
|
||||
unitPrice: partida.unitPrice,
|
||||
sequence: partida.sequence,
|
||||
createdById: ctx.userId,
|
||||
}));
|
||||
}
|
||||
return newVersion;
|
||||
}
|
||||
/**
|
||||
* Aprobar presupuesto
|
||||
*/
|
||||
async approve(ctx, presupuestoId) {
|
||||
const presupuesto = await this.findById(ctx, presupuestoId);
|
||||
if (!presupuesto) {
|
||||
return null;
|
||||
}
|
||||
return this.update(ctx, presupuestoId, {
|
||||
approvedAt: new Date(),
|
||||
approvedById: ctx.userId,
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.PresupuestoService = PresupuestoService;
|
||||
//# sourceMappingURL=presupuesto.service.js.map
|
||||
1
dist/modules/budgets/services/presupuesto.service.js.map
vendored
Normal file
1
dist/modules/budgets/services/presupuesto.service.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"presupuesto.service.js","sourceRoot":"","sources":["../../../../src/modules/budgets/services/presupuesto.service.ts"],"names":[],"mappings":"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"}
|
||||
15
dist/modules/construction/controllers/etapa.controller.d.ts
vendored
Normal file
15
dist/modules/construction/controllers/etapa.controller.d.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* EtapaController - Controller de etapas
|
||||
*
|
||||
* Endpoints REST para gestión de etapas de fraccionamientos.
|
||||
*
|
||||
* @module Construction
|
||||
*/
|
||||
import { Router } from 'express';
|
||||
import { DataSource } from 'typeorm';
|
||||
/**
|
||||
* Crear router de etapas
|
||||
*/
|
||||
export declare function createEtapaController(dataSource: DataSource): Router;
|
||||
export default createEtapaController;
|
||||
//# sourceMappingURL=etapa.controller.d.ts.map
|
||||
1
dist/modules/construction/controllers/etapa.controller.d.ts.map
vendored
Normal file
1
dist/modules/construction/controllers/etapa.controller.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"etapa.controller.d.ts","sourceRoot":"","sources":["../../../../src/modules/construction/controllers/etapa.controller.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAmC,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AASrC;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CA6JpE;AAED,eAAe,qBAAqB,CAAC"}
|
||||
168
dist/modules/construction/controllers/etapa.controller.js
vendored
Normal file
168
dist/modules/construction/controllers/etapa.controller.js
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
"use strict";
|
||||
/**
|
||||
* EtapaController - Controller de etapas
|
||||
*
|
||||
* Endpoints REST para gestión de etapas de fraccionamientos.
|
||||
*
|
||||
* @module Construction
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createEtapaController = createEtapaController;
|
||||
const express_1 = require("express");
|
||||
const etapa_service_1 = require("../services/etapa.service");
|
||||
const auth_middleware_1 = require("../../auth/middleware/auth.middleware");
|
||||
const auth_service_1 = require("../../auth/services/auth.service");
|
||||
const etapa_entity_1 = require("../entities/etapa.entity");
|
||||
const user_entity_1 = require("../../core/entities/user.entity");
|
||||
const tenant_entity_1 = require("../../core/entities/tenant.entity");
|
||||
const refresh_token_entity_1 = require("../../auth/entities/refresh-token.entity");
|
||||
/**
|
||||
* Crear router de etapas
|
||||
*/
|
||||
function createEtapaController(dataSource) {
|
||||
const router = (0, express_1.Router)();
|
||||
// Repositorios
|
||||
const etapaRepository = dataSource.getRepository(etapa_entity_1.Etapa);
|
||||
const userRepository = dataSource.getRepository(user_entity_1.User);
|
||||
const tenantRepository = dataSource.getRepository(tenant_entity_1.Tenant);
|
||||
const refreshTokenRepository = dataSource.getRepository(refresh_token_entity_1.RefreshToken);
|
||||
// Servicios
|
||||
const etapaService = new etapa_service_1.EtapaService(etapaRepository);
|
||||
const authService = new auth_service_1.AuthService(userRepository, tenantRepository, refreshTokenRepository);
|
||||
const authMiddleware = new auth_middleware_1.AuthMiddleware(authService, dataSource);
|
||||
/**
|
||||
* GET /etapas
|
||||
* Listar etapas
|
||||
*/
|
||||
router.get('/', authMiddleware.authenticate, async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const page = parseInt(req.query.page) || 1;
|
||||
const limit = Math.min(parseInt(req.query.limit) || 20, 100);
|
||||
const search = req.query.search;
|
||||
const status = req.query.status;
|
||||
const fraccionamientoId = req.query.fraccionamientoId;
|
||||
const result = await etapaService.findAll({ tenantId, page, limit, search, status, fraccionamientoId });
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
data: result.items,
|
||||
pagination: {
|
||||
page,
|
||||
limit,
|
||||
total: result.total,
|
||||
totalPages: Math.ceil(result.total / limit),
|
||||
},
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* GET /etapas/:id
|
||||
* Obtener etapa por ID
|
||||
*/
|
||||
router.get('/:id', authMiddleware.authenticate, async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const etapa = await etapaService.findById(req.params.id, tenantId);
|
||||
if (!etapa) {
|
||||
res.status(404).json({ error: 'Not Found', message: 'Stage not found' });
|
||||
return;
|
||||
}
|
||||
res.status(200).json({ success: true, data: etapa });
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* POST /etapas
|
||||
* Crear etapa
|
||||
*/
|
||||
router.post('/', authMiddleware.authenticate, authMiddleware.authorize('admin', 'engineer', 'director'), async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const dto = req.body;
|
||||
if (!dto.fraccionamientoId || !dto.code || !dto.name) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'fraccionamientoId, code and name are required' });
|
||||
return;
|
||||
}
|
||||
const etapa = await etapaService.create(tenantId, dto, req.user?.sub);
|
||||
res.status(201).json({ success: true, data: etapa });
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof Error && error.message.includes('already exists')) {
|
||||
res.status(409).json({ error: 'Conflict', message: error.message });
|
||||
return;
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* PATCH /etapas/:id
|
||||
* Actualizar etapa
|
||||
*/
|
||||
router.patch('/:id', authMiddleware.authenticate, authMiddleware.authorize('admin', 'engineer', 'director'), async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
const dto = req.body;
|
||||
const etapa = await etapaService.update(req.params.id, tenantId, dto, req.user?.sub);
|
||||
res.status(200).json({ success: true, data: etapa });
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof Error) {
|
||||
if (error.message === 'Stage not found') {
|
||||
res.status(404).json({ error: 'Not Found', message: error.message });
|
||||
return;
|
||||
}
|
||||
if (error.message.includes('already exists')) {
|
||||
res.status(409).json({ error: 'Conflict', message: error.message });
|
||||
return;
|
||||
}
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* DELETE /etapas/:id
|
||||
* Eliminar etapa
|
||||
*/
|
||||
router.delete('/:id', authMiddleware.authenticate, authMiddleware.authorize('admin', 'director'), async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.tenantId;
|
||||
if (!tenantId) {
|
||||
res.status(400).json({ error: 'Bad Request', message: 'Tenant ID required' });
|
||||
return;
|
||||
}
|
||||
await etapaService.delete(req.params.id, tenantId, req.user?.sub);
|
||||
res.status(200).json({ success: true, message: 'Stage deleted' });
|
||||
}
|
||||
catch (error) {
|
||||
if (error instanceof Error && error.message === 'Stage not found') {
|
||||
res.status(404).json({ error: 'Not Found', message: error.message });
|
||||
return;
|
||||
}
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
return router;
|
||||
}
|
||||
exports.default = createEtapaController;
|
||||
//# sourceMappingURL=etapa.controller.js.map
|
||||
1
dist/modules/construction/controllers/etapa.controller.js.map
vendored
Normal file
1
dist/modules/construction/controllers/etapa.controller.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
10
dist/modules/construction/controllers/fraccionamiento.controller.d.ts
vendored
Normal file
10
dist/modules/construction/controllers/fraccionamiento.controller.d.ts
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Fraccionamiento Controller
|
||||
* API endpoints para gestión de fraccionamientos/obras
|
||||
*
|
||||
* @module Construction
|
||||
* @prefix /api/v1/fraccionamientos
|
||||
*/
|
||||
declare const router: import("express-serve-static-core").Router;
|
||||
export default router;
|
||||
//# sourceMappingURL=fraccionamiento.controller.d.ts.map
|
||||
1
dist/modules/construction/controllers/fraccionamiento.controller.d.ts.map
vendored
Normal file
1
dist/modules/construction/controllers/fraccionamiento.controller.d.ts.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"fraccionamiento.controller.d.ts","sourceRoot":"","sources":["../../../../src/modules/construction/controllers/fraccionamiento.controller.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,QAAA,MAAM,MAAM,4CAAW,CAAC;AA6IxB,eAAe,MAAM,CAAC"}
|
||||
135
dist/modules/construction/controllers/fraccionamiento.controller.js
vendored
Normal file
135
dist/modules/construction/controllers/fraccionamiento.controller.js
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
"use strict";
|
||||
/**
|
||||
* Fraccionamiento Controller
|
||||
* API endpoints para gestión de fraccionamientos/obras
|
||||
*
|
||||
* @module Construction
|
||||
* @prefix /api/v1/fraccionamientos
|
||||
*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = require("express");
|
||||
const fraccionamiento_service_1 = require("../services/fraccionamiento.service");
|
||||
const router = (0, express_1.Router)();
|
||||
const fraccionamientoService = new fraccionamiento_service_1.FraccionamientoService();
|
||||
/**
|
||||
* GET /api/v1/fraccionamientos
|
||||
* Lista todos los fraccionamientos del tenant
|
||||
*/
|
||||
router.get('/', async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.headers['x-tenant-id'];
|
||||
if (!tenantId) {
|
||||
return res.status(400).json({ error: 'X-Tenant-Id header required' });
|
||||
}
|
||||
const { proyectoId, estado } = req.query;
|
||||
const fraccionamientos = await fraccionamientoService.findAll({
|
||||
tenantId,
|
||||
proyectoId: proyectoId,
|
||||
estado: estado,
|
||||
});
|
||||
return res.json({
|
||||
success: true,
|
||||
data: fraccionamientos,
|
||||
count: fraccionamientos.length,
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* GET /api/v1/fraccionamientos/:id
|
||||
* Obtiene un fraccionamiento por ID
|
||||
*/
|
||||
router.get('/:id', async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.headers['x-tenant-id'];
|
||||
if (!tenantId) {
|
||||
return res.status(400).json({ error: 'X-Tenant-Id header required' });
|
||||
}
|
||||
const fraccionamiento = await fraccionamientoService.findById(req.params.id, tenantId);
|
||||
if (!fraccionamiento) {
|
||||
return res.status(404).json({ error: 'Fraccionamiento no encontrado' });
|
||||
}
|
||||
return res.json({ success: true, data: fraccionamiento });
|
||||
}
|
||||
catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* POST /api/v1/fraccionamientos
|
||||
* Crea un nuevo fraccionamiento
|
||||
*/
|
||||
router.post('/', async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.headers['x-tenant-id'];
|
||||
if (!tenantId) {
|
||||
return res.status(400).json({ error: 'X-Tenant-Id header required' });
|
||||
}
|
||||
const data = {
|
||||
...req.body,
|
||||
tenantId,
|
||||
createdById: req.user?.id,
|
||||
};
|
||||
// Validate required fields
|
||||
if (!data.codigo || !data.nombre || !data.proyectoId) {
|
||||
return res.status(400).json({
|
||||
error: 'codigo, nombre y proyectoId son requeridos'
|
||||
});
|
||||
}
|
||||
// Check if codigo already exists
|
||||
const existing = await fraccionamientoService.findByCodigo(data.codigo, tenantId);
|
||||
if (existing) {
|
||||
return res.status(409).json({ error: 'Ya existe un fraccionamiento con ese código' });
|
||||
}
|
||||
const fraccionamiento = await fraccionamientoService.create(data);
|
||||
return res.status(201).json({ success: true, data: fraccionamiento });
|
||||
}
|
||||
catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* PATCH /api/v1/fraccionamientos/:id
|
||||
* Actualiza un fraccionamiento
|
||||
*/
|
||||
router.patch('/:id', async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.headers['x-tenant-id'];
|
||||
if (!tenantId) {
|
||||
return res.status(400).json({ error: 'X-Tenant-Id header required' });
|
||||
}
|
||||
const data = req.body;
|
||||
const fraccionamiento = await fraccionamientoService.update(req.params.id, tenantId, data);
|
||||
if (!fraccionamiento) {
|
||||
return res.status(404).json({ error: 'Fraccionamiento no encontrado' });
|
||||
}
|
||||
return res.json({ success: true, data: fraccionamiento });
|
||||
}
|
||||
catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
});
|
||||
/**
|
||||
* DELETE /api/v1/fraccionamientos/:id
|
||||
* Elimina un fraccionamiento
|
||||
*/
|
||||
router.delete('/:id', async (req, res, next) => {
|
||||
try {
|
||||
const tenantId = req.headers['x-tenant-id'];
|
||||
if (!tenantId) {
|
||||
return res.status(400).json({ error: 'X-Tenant-Id header required' });
|
||||
}
|
||||
const deleted = await fraccionamientoService.delete(req.params.id, tenantId);
|
||||
if (!deleted) {
|
||||
return res.status(404).json({ error: 'Fraccionamiento no encontrado' });
|
||||
}
|
||||
return res.json({ success: true, message: 'Fraccionamiento eliminado' });
|
||||
}
|
||||
catch (error) {
|
||||
return next(error);
|
||||
}
|
||||
});
|
||||
exports.default = router;
|
||||
//# sourceMappingURL=fraccionamiento.controller.js.map
|
||||
1
dist/modules/construction/controllers/fraccionamiento.controller.js.map
vendored
Normal file
1
dist/modules/construction/controllers/fraccionamiento.controller.js.map
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"fraccionamiento.controller.js","sourceRoot":"","sources":["../../../../src/modules/construction/controllers/fraccionamiento.controller.ts"],"names":[],"mappings":"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"}
|
||||
11
dist/modules/construction/controllers/index.d.ts
vendored
Normal file
11
dist/modules/construction/controllers/index.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Construction Controllers Index
|
||||
* @module Construction
|
||||
*/
|
||||
export { default as proyectoController } from './proyecto.controller';
|
||||
export { default as fraccionamientoController } from './fraccionamiento.controller';
|
||||
export { createEtapaController } from './etapa.controller';
|
||||
export { createManzanaController } from './manzana.controller';
|
||||
export { createLoteController } from './lote.controller';
|
||||
export { createPrototipoController } from './prototipo.controller';
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user