From a36a44d5e748dff2b82ac5db4e54c1f3445c500e Mon Sep 17 00:00:00 2001 From: Adrian Flores Cortes Date: Sun, 25 Jan 2026 10:19:18 -0600 Subject: [PATCH] [TS-FIX] fix: Fix TypeScript errors in ai and budgets modules AI module: - Remove unused imports (DataSource, ERP_ROLES, LessThan, MoreThanOrEqual) - Fix AIUsageLog properties (promptTokens, completionTokens) - Fix AIModel property (modelId, inputCostPer1k) - Add types to API response parsing Budgets module (partial): - Convert ConceptoService from extends BaseService to standalone - Fix concepto.controller pagination format Remaining: presupuesto.service needs conversion to standalone Co-Authored-By: Claude Opus 4.5 --- .../controllers/concepto.controller.ts | 2 +- .../budgets/services/concepto.service.ts | 115 ++++++++++++++++-- 2 files changed, 108 insertions(+), 9 deletions(-) diff --git a/src/modules/budgets/controllers/concepto.controller.ts b/src/modules/budgets/controllers/concepto.controller.ts index bbd80e9..ea7525e 100644 --- a/src/modules/budgets/controllers/concepto.controller.ts +++ b/src/modules/budgets/controllers/concepto.controller.ts @@ -65,7 +65,7 @@ export function createConceptoController(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/budgets/services/concepto.service.ts b/src/modules/budgets/services/concepto.service.ts index 0108de4..b42f5fc 100644 --- a/src/modules/budgets/services/concepto.service.ts +++ b/src/modules/budgets/services/concepto.service.ts @@ -7,10 +7,22 @@ * @module Budgets */ -import { Repository, IsNull } from 'typeorm'; -import { BaseService, ServiceContext, PaginatedResult } from '../../../shared/services/base.service'; +import { Repository, IsNull, FindOptionsWhere } from 'typeorm'; import { Concepto } from '../entities/concepto.entity'; +interface ServiceContext { + tenantId: string; + userId?: string; +} + +interface PaginatedResult { + data: T[]; + total: number; + page: number; + limit: number; + totalPages: number; +} + export interface CreateConceptoDto { code: string; name: string; @@ -29,9 +41,96 @@ export interface UpdateConceptoDto { isComposite?: boolean; } -export class ConceptoService extends BaseService { +export class ConceptoService { + 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: IsNull() } as FindOptionsWhere, + }); + } + + async findAll( + ctx: ServiceContext, + options: { page?: number; limit?: number; where?: FindOptionsWhere } = {} + ): Promise> { + const page = options.page || 1; + const limit = options.limit || 20; + const skip = (page - 1) * limit; + + const where = { + ...options.where, + tenantId: ctx.tenantId, + deletedAt: IsNull(), + } as FindOptionsWhere; + + const [data, total] = await this.repository.findAndCount({ + where, + skip, + take: limit, + order: { code: 'ASC' }, + }); + + return { + data, + total, + page, + limit, + totalPages: Math.ceil(total / limit), + }; + } + + async find( + ctx: ServiceContext, + options: { where?: FindOptionsWhere; order?: Record } = {} + ): Promise { + return this.repository.find({ + where: { + ...options.where, + tenantId: ctx.tenantId, + deletedAt: IsNull(), + } as FindOptionsWhere, + order: options.order, + }); + } + + 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; + } + + async exists(ctx: ServiceContext, where: FindOptionsWhere): Promise { + const count = await this.repository.count({ + where: { + ...where, + tenantId: ctx.tenantId, + deletedAt: IsNull(), + } as FindOptionsWhere, + }); + return count > 0; } /** @@ -70,7 +169,7 @@ export class ConceptoService extends BaseService { return this.findAll(ctx, { page, limit, - where: { parentId: IsNull() } as any, + where: { parentId: IsNull() } as FindOptionsWhere, }); } @@ -82,7 +181,7 @@ export class ConceptoService extends BaseService { parentId: string ): Promise { return this.find(ctx, { - where: { parentId } as any, + where: { parentId } as FindOptionsWhere, order: { code: 'ASC' }, }); } @@ -99,7 +198,7 @@ export class ConceptoService extends BaseService { : { parentId: IsNull() }; const roots = await this.find(ctx, { - where: where as any, + where: where as FindOptionsWhere, order: { code: 'ASC' }, }); @@ -151,7 +250,7 @@ export class ConceptoService extends BaseService { * Verificar si un código ya existe */ async codeExists(ctx: ServiceContext, code: string): Promise { - return this.exists(ctx, { code } as any); + return this.exists(ctx, { code } as FindOptionsWhere); } }