diff --git a/src/modules/admin/controllers/audit-log.controller.ts b/src/modules/admin/controllers/audit-log.controller.ts index 13a4b3a..421a814 100644 --- a/src/modules/admin/controllers/audit-log.controller.ts +++ b/src/modules/admin/controllers/audit-log.controller.ts @@ -15,7 +15,11 @@ import { AuditLog } from '../entities/audit-log.entity'; import { User } from '../../core/entities/user.entity'; import { Tenant } from '../../core/entities/tenant.entity'; import { RefreshToken } from '../../auth/entities/refresh-token.entity'; -import { ServiceContext } from '../../../shared/services/base.service'; + +interface ServiceContext { + tenantId: string; + userId?: string; +} export function createAuditLogController(dataSource: DataSource): Router { const router = Router(); @@ -74,7 +78,7 @@ export function createAuditLogController(dataSource: DataSource): Router { res.status(200).json({ success: true, data: result.data, - pagination: result.meta, + pagination: { total: result.total, page: result.page, limit: result.limit, totalPages: result.totalPages }, }); } catch (error) { next(error); @@ -164,7 +168,7 @@ export function createAuditLogController(dataSource: DataSource): Router { res.status(200).json({ success: true, data: result.data, - pagination: result.meta, + pagination: { total: result.total, page: result.page, limit: result.limit, totalPages: result.totalPages }, }); } catch (error) { next(error); @@ -194,7 +198,7 @@ export function createAuditLogController(dataSource: DataSource): Router { res.status(200).json({ success: true, data: result.data, - pagination: result.meta, + pagination: { total: result.total, page: result.page, limit: result.limit, totalPages: result.totalPages }, }); } catch (error) { next(error); diff --git a/src/modules/admin/controllers/backup.controller.ts b/src/modules/admin/controllers/backup.controller.ts index 826253c..509e440 100644 --- a/src/modules/admin/controllers/backup.controller.ts +++ b/src/modules/admin/controllers/backup.controller.ts @@ -15,7 +15,11 @@ import { Backup } from '../entities/backup.entity'; import { User } from '../../core/entities/user.entity'; import { Tenant } from '../../core/entities/tenant.entity'; import { RefreshToken } from '../../auth/entities/refresh-token.entity'; -import { ServiceContext } from '../../../shared/services/base.service'; + +interface ServiceContext { + tenantId: string; + userId?: string; +} export function createBackupController(dataSource: DataSource): Router { const router = Router(); @@ -69,7 +73,7 @@ export function createBackupController(dataSource: DataSource): Router { res.status(200).json({ success: true, data: result.data, - pagination: result.meta, + pagination: { total: result.total, page: result.page, limit: result.limit, totalPages: result.totalPages }, }); } catch (error) { next(error); diff --git a/src/modules/admin/controllers/cost-center.controller.ts b/src/modules/admin/controllers/cost-center.controller.ts index c72f94d..8495e8f 100644 --- a/src/modules/admin/controllers/cost-center.controller.ts +++ b/src/modules/admin/controllers/cost-center.controller.ts @@ -15,7 +15,11 @@ import { CostCenter } from '../entities/cost-center.entity'; import { User } from '../../core/entities/user.entity'; import { Tenant } from '../../core/entities/tenant.entity'; import { RefreshToken } from '../../auth/entities/refresh-token.entity'; -import { ServiceContext } from '../../../shared/services/base.service'; + +interface ServiceContext { + tenantId: string; + userId?: string; +} export function createCostCenterController(dataSource: DataSource): Router { const router = Router(); @@ -69,7 +73,7 @@ export function createCostCenterController(dataSource: DataSource): Router { res.status(200).json({ success: true, data: result.data, - pagination: result.meta, + pagination: { total: result.total, page: result.page, limit: result.limit, totalPages: result.totalPages }, }); } catch (error) { next(error); diff --git a/src/modules/admin/controllers/system-setting.controller.ts b/src/modules/admin/controllers/system-setting.controller.ts index 1638d68..535f76f 100644 --- a/src/modules/admin/controllers/system-setting.controller.ts +++ b/src/modules/admin/controllers/system-setting.controller.ts @@ -15,7 +15,11 @@ import { SystemSetting } from '../entities/system-setting.entity'; import { User } from '../../core/entities/user.entity'; import { Tenant } from '../../core/entities/tenant.entity'; import { RefreshToken } from '../../auth/entities/refresh-token.entity'; -import { ServiceContext } from '../../../shared/services/base.service'; + +interface ServiceContext { + tenantId: string; + userId?: string; +} export function createSystemSettingController(dataSource: DataSource): Router { const router = Router(); @@ -65,7 +69,7 @@ export function createSystemSettingController(dataSource: DataSource): Router { res.status(200).json({ success: true, data: result.data, - pagination: result.meta, + pagination: { total: result.total, page: result.page, limit: result.limit, totalPages: result.totalPages }, }); } catch (error) { next(error); diff --git a/src/modules/admin/services/audit-log.service.ts b/src/modules/admin/services/audit-log.service.ts index 2a1706c..fb3e57e 100644 --- a/src/modules/admin/services/audit-log.service.ts +++ b/src/modules/admin/services/audit-log.service.ts @@ -7,9 +7,21 @@ */ import { Repository } from 'typeorm'; -import { ServiceContext, PaginatedResult } from '../../../shared/services/base.service'; import { AuditLog, AuditCategory, AuditAction, AuditSeverity } from '../entities/audit-log.entity'; +interface ServiceContext { + tenantId: string; + userId?: string; +} + +interface PaginatedResult { + data: T[]; + total: number; + page: number; + limit: number; + totalPages: number; +} + export interface CreateAuditLogDto { userId?: string; category: AuditCategory; @@ -138,12 +150,10 @@ export class AuditLogService { return { data, - meta: { - total, - page, - limit, - totalPages: Math.ceil(total / limit), - }, + total, + page, + limit, + totalPages: Math.ceil(total / limit), }; } diff --git a/src/modules/admin/services/backup.service.ts b/src/modules/admin/services/backup.service.ts index 745399e..442cb9e 100644 --- a/src/modules/admin/services/backup.service.ts +++ b/src/modules/admin/services/backup.service.ts @@ -7,9 +7,21 @@ */ import { Repository } from 'typeorm'; -import { BaseService, ServiceContext, PaginatedResult } from '../../../shared/services/base.service'; import { Backup, BackupType, BackupStatus, BackupStorage } from '../entities/backup.entity'; +interface ServiceContext { + tenantId: string; + userId?: string; +} + +interface PaginatedResult { + data: T[]; + total: number; + page: number; + limit: number; + totalPages: number; +} + export interface CreateBackupDto { backupType: BackupType; name: string; @@ -33,9 +45,38 @@ export interface BackupFilters { dateTo?: Date; } -export class BackupService extends BaseService { +export class BackupService { + private repository: Repository; + constructor(repository: Repository) { - super(repository); + this.repository = repository; + } + + async create(ctx: ServiceContext, data: Partial): Promise { + const entity = this.repository.create({ + ...data, + tenantId: ctx.tenantId, + createdById: ctx.userId, + }); + return this.repository.save(entity); + } + + async findById(ctx: ServiceContext, id: string): Promise { + return this.repository.findOne({ + where: { id, tenantId: ctx.tenantId } as any, + }); + } + + async update(ctx: ServiceContext, id: string, data: Partial): Promise { + const entity = await this.findById(ctx, id); + if (!entity) return null; + Object.assign(entity, data); + return this.repository.save(entity); + } + + async softDelete(ctx: ServiceContext, id: string): Promise { + const result = await this.repository.delete({ id, tenantId: ctx.tenantId } as any); + return (result.affected || 0) > 0; } /** @@ -81,12 +122,10 @@ export class BackupService extends BaseService { return { data, - meta: { - total, - page, - limit, - totalPages: Math.ceil(total / limit), - }, + total, + page, + limit, + totalPages: Math.ceil(total / limit), }; } diff --git a/src/modules/admin/services/cost-center.service.ts b/src/modules/admin/services/cost-center.service.ts index ede0ae9..7fdc152 100644 --- a/src/modules/admin/services/cost-center.service.ts +++ b/src/modules/admin/services/cost-center.service.ts @@ -7,9 +7,21 @@ */ import { Repository } from 'typeorm'; -import { BaseService, ServiceContext, PaginatedResult } from '../../../shared/services/base.service'; import { CostCenter, CostCenterType, CostCenterLevel } from '../entities/cost-center.entity'; +interface ServiceContext { + tenantId: string; + userId?: string; +} + +interface PaginatedResult { + data: T[]; + total: number; + page: number; + limit: number; + totalPages: number; +} + export interface CreateCostCenterDto { code: string; name: string; @@ -42,9 +54,41 @@ export interface CostCenterFilters { search?: string; } -export class CostCenterService extends BaseService { +export class CostCenterService { + private repository: Repository; + constructor(repository: Repository) { - super(repository); + this.repository = repository; + } + + async create(ctx: ServiceContext, data: Partial): Promise { + const entity = this.repository.create({ + ...data, + tenantId: ctx.tenantId, + createdById: ctx.userId, + }); + return this.repository.save(entity); + } + + async findById(ctx: ServiceContext, id: string): Promise { + return this.repository.findOne({ + where: { id, tenantId: ctx.tenantId, deletedAt: null } as any, + }); + } + + async update(ctx: ServiceContext, id: string, data: Partial): Promise { + const entity = await this.findById(ctx, id); + if (!entity) return null; + Object.assign(entity, data); + return this.repository.save(entity); + } + + async softDelete(ctx: ServiceContext, id: string): Promise { + const entity = await this.findById(ctx, id); + if (!entity) return false; + entity.deletedAt = new Date(); + await this.repository.save(entity); + return true; } /** @@ -100,12 +144,10 @@ export class CostCenterService extends BaseService { return { data, - meta: { - total, - page, - limit, - totalPages: Math.ceil(total / limit), - }, + total, + page, + limit, + totalPages: Math.ceil(total / limit), }; } diff --git a/src/modules/admin/services/system-setting.service.ts b/src/modules/admin/services/system-setting.service.ts index 3daf8f6..6dab979 100644 --- a/src/modules/admin/services/system-setting.service.ts +++ b/src/modules/admin/services/system-setting.service.ts @@ -7,9 +7,21 @@ */ import { Repository } from 'typeorm'; -import { BaseService, ServiceContext, PaginatedResult } from '../../../shared/services/base.service'; import { SystemSetting, SettingCategory, SettingDataType } from '../entities/system-setting.entity'; +interface ServiceContext { + tenantId: string; + userId?: string; +} + +interface PaginatedResult { + data: T[]; + total: number; + page: number; + limit: number; + totalPages: number; +} + export interface CreateSettingDto { key: string; name: string; @@ -43,9 +55,37 @@ export interface SettingFilters { search?: string; } -export class SystemSettingService extends BaseService { +export class SystemSettingService { + private repository: Repository; + constructor(repository: Repository) { - super(repository); + this.repository = repository; + } + + async create(ctx: ServiceContext, data: Partial): Promise { + const entity = this.repository.create({ + ...data, + tenantId: ctx.tenantId, + }); + return this.repository.save(entity); + } + + async findById(ctx: ServiceContext, id: string): Promise { + return this.repository.findOne({ + where: { id, tenantId: ctx.tenantId } as any, + }); + } + + async update(ctx: ServiceContext, id: string, data: Partial): Promise { + const entity = await this.findById(ctx, id); + if (!entity) return null; + Object.assign(entity, data); + return this.repository.save(entity); + } + + async hardDelete(ctx: ServiceContext, id: string): Promise { + const result = await this.repository.delete({ id, tenantId: ctx.tenantId } as any); + return (result.affected || 0) > 0; } /** @@ -117,12 +157,10 @@ export class SystemSettingService extends BaseService { return { data, - meta: { - total, - page, - limit, - totalPages: Math.ceil(total / limit), - }, + total, + page, + limit, + totalPages: Math.ceil(total / limit), }; } diff --git a/src/modules/bidding/controllers/bid-budget.controller.ts b/src/modules/bidding/controllers/bid-budget.controller.ts index b1227ff..8f51b60 100644 --- a/src/modules/bidding/controllers/bid-budget.controller.ts +++ b/src/modules/bidding/controllers/bid-budget.controller.ts @@ -74,7 +74,7 @@ export function createBidBudgetController(dataSource: DataSource): Router { res.status(200).json({ success: true, data: result.data, - pagination: result.meta, + pagination: { total: result.total, page: result.page, limit: result.limit, totalPages: result.totalPages }, }); } catch (error) { next(error); diff --git a/src/modules/bidding/controllers/bid.controller.ts b/src/modules/bidding/controllers/bid.controller.ts index 6ab1122..aa9babc 100644 --- a/src/modules/bidding/controllers/bid.controller.ts +++ b/src/modules/bidding/controllers/bid.controller.ts @@ -76,7 +76,7 @@ export function createBidController(dataSource: DataSource): Router { res.status(200).json({ success: true, data: result.data, - pagination: result.meta, + pagination: { total: result.total, page: result.page, limit: result.limit, totalPages: result.totalPages }, }); } catch (error) { next(error); diff --git a/src/modules/bidding/controllers/opportunity.controller.ts b/src/modules/bidding/controllers/opportunity.controller.ts index ce35ed5..b27b607 100644 --- a/src/modules/bidding/controllers/opportunity.controller.ts +++ b/src/modules/bidding/controllers/opportunity.controller.ts @@ -77,7 +77,7 @@ export function createOpportunityController(dataSource: DataSource): Router { res.status(200).json({ success: true, data: result.data, - pagination: result.meta, + pagination: { total: result.total, page: result.page, limit: result.limit, totalPages: result.totalPages }, }); } catch (error) { next(error); diff --git a/src/modules/bidding/services/bid-budget.service.ts b/src/modules/bidding/services/bid-budget.service.ts index f156b70..9bbf3a3 100644 --- a/src/modules/bidding/services/bid-budget.service.ts +++ b/src/modules/bidding/services/bid-budget.service.ts @@ -190,12 +190,10 @@ export class BidBudgetService { return { data, - meta: { - total, - page, - limit, - totalPages: Math.ceil(total / limit), - }, + total, + page, + limit, + totalPages: Math.ceil(total / limit), }; } diff --git a/src/modules/bidding/services/bid.service.ts b/src/modules/bidding/services/bid.service.ts index 13e1469..0cf6969 100644 --- a/src/modules/bidding/services/bid.service.ts +++ b/src/modules/bidding/services/bid.service.ts @@ -162,12 +162,10 @@ export class BidService { return { data, - meta: { - total, - page, - limit, - totalPages: Math.ceil(total / limit), - }, + total, + page, + limit, + totalPages: Math.ceil(total / limit), }; } diff --git a/src/modules/bidding/services/opportunity.service.ts b/src/modules/bidding/services/opportunity.service.ts index e67f9ff..e0ac765 100644 --- a/src/modules/bidding/services/opportunity.service.ts +++ b/src/modules/bidding/services/opportunity.service.ts @@ -200,12 +200,10 @@ export class OpportunityService { return { data, - meta: { - total, - page, - limit, - totalPages: Math.ceil(total / limit), - }, + total, + page, + limit, + totalPages: Math.ceil(total / limit), }; } diff --git a/src/shared/services/base.service.ts b/src/shared/services/base.service.ts index e368b92..6886014 100644 --- a/src/shared/services/base.service.ts +++ b/src/shared/services/base.service.ts @@ -2,6 +2,14 @@ import { query, queryOne, getClient, PoolClient } from '../../config/database.js import { NotFoundError, ValidationError } from '../errors/index.js'; import { PaginationMeta } from '../types/index.js'; +/** + * Contexto de servicio para multi-tenant + */ +export interface ServiceContext { + tenantId: string; + userId?: string; +} + /** * Resultado paginado genérico */