diff --git a/src/modules/contracts/controllers/contract.controller.ts b/src/modules/contracts/controllers/contract.controller.ts index ed8bd49..e7f1fff 100644 --- a/src/modules/contracts/controllers/contract.controller.ts +++ b/src/modules/contracts/controllers/contract.controller.ts @@ -17,7 +17,11 @@ import { AuthService } from '../../auth/services/auth.service'; 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 createContractController(dataSource: DataSource): Router { const router = Router(); @@ -69,7 +73,7 @@ export function createContractController(dataSource: DataSource): Router { const limit = Math.min(parseInt(req.query.limit as string) || 20, 100); const result = await service.findWithFilters(getContext(req), filters, page, limit); - res.status(200).json({ success: true, data: result.data, pagination: result.meta }); + res.status(200).json({ success: true, data: result.data, pagination: { total: result.total, page: result.page, limit: result.limit } }); } catch (error) { next(error); } diff --git a/src/modules/contracts/controllers/subcontractor.controller.ts b/src/modules/contracts/controllers/subcontractor.controller.ts index a29365f..4c59ece 100644 --- a/src/modules/contracts/controllers/subcontractor.controller.ts +++ b/src/modules/contracts/controllers/subcontractor.controller.ts @@ -16,7 +16,11 @@ import { AuthService } from '../../auth/services/auth.service'; 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 createSubcontractorController(dataSource: DataSource): Router { const router = Router(); @@ -65,7 +69,7 @@ export function createSubcontractorController(dataSource: DataSource): Router { const limit = Math.min(parseInt(req.query.limit as string) || 20, 100); const result = await service.findWithFilters(getContext(req), filters, page, limit); - res.status(200).json({ success: true, data: result.data, pagination: result.meta }); + res.status(200).json({ success: true, data: result.data, pagination: { total: result.total, page: result.page, limit: result.limit } }); } catch (error) { next(error); } diff --git a/src/modules/contracts/entities/contract-addendum.entity.ts b/src/modules/contracts/entities/contract-addendum.entity.ts index fd3cdd9..e0ae18a 100644 --- a/src/modules/contracts/entities/contract-addendum.entity.ts +++ b/src/modules/contracts/entities/contract-addendum.entity.ts @@ -23,7 +23,7 @@ import { Contract } from './contract.entity'; export type AddendumType = 'extension' | 'amount_increase' | 'amount_decrease' | 'scope_change' | 'termination' | 'other'; export type AddendumStatus = 'draft' | 'review' | 'approved' | 'rejected'; -@Entity({ schema: 'contracts', name: 'contract_addendums' }) +@Entity({ schema: 'construction', name: 'contrato_addendas' }) @Index(['tenantId', 'addendumNumber'], { unique: true }) export class ContractAddendum { @PrimaryGeneratedColumn('uuid') diff --git a/src/modules/contracts/entities/contract-partida.entity.ts b/src/modules/contracts/entities/contract-partida.entity.ts new file mode 100644 index 0000000..edf2253 --- /dev/null +++ b/src/modules/contracts/entities/contract-partida.entity.ts @@ -0,0 +1,75 @@ +/** + * ContractPartida Entity + * Partidas/lineas de contratos con subcontratistas + * + * @module Contracts + * @table construction.contrato_partidas + */ + +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, + ManyToOne, + JoinColumn, +} from 'typeorm'; +import { Tenant } from '../../core/entities/tenant.entity'; +import { User } from '../../core/entities/user.entity'; +import { Contract } from './contract.entity'; + +@Entity({ schema: 'construction', name: 'contrato_partidas' }) +export class ContractPartida { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column({ name: 'tenant_id', type: 'uuid' }) + tenantId: string; + + @Column({ name: 'contrato_id', type: 'uuid' }) + contractId: string; + + @Column({ name: 'concepto_id', type: 'uuid' }) + conceptoId: string; + + @Column({ type: 'decimal', precision: 12, scale: 4, default: 0 }) + quantity: number; + + @Column({ name: 'unit_price', type: 'decimal', precision: 12, scale: 4, default: 0 }) + unitPrice: number; + + @Column({ name: 'total_amount', type: 'decimal', precision: 14, scale: 2, insert: false, update: false }) + totalAmount: number; + + @CreateDateColumn({ name: 'created_at', type: 'timestamptz' }) + createdAt: Date; + + @Column({ name: 'created_by', type: 'uuid', nullable: true }) + createdById: string; + + @UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' }) + updatedAt: Date; + + @Column({ name: 'updated_by', type: 'uuid', nullable: true }) + updatedById: string; + + @Column({ name: 'deleted_at', type: 'timestamptz', nullable: true }) + deletedAt: Date; + + @Column({ name: 'deleted_by', type: 'uuid', nullable: true }) + deletedById: string; + + // Relations + @ManyToOne(() => Tenant) + @JoinColumn({ name: 'tenant_id' }) + tenant: Tenant; + + @ManyToOne(() => Contract, { onDelete: 'CASCADE' }) + @JoinColumn({ name: 'contrato_id' }) + contract: Contract; + + @ManyToOne(() => User) + @JoinColumn({ name: 'created_by' }) + createdBy: User; +} diff --git a/src/modules/contracts/entities/contract.entity.ts b/src/modules/contracts/entities/contract.entity.ts index b416f03..aa4eef5 100644 --- a/src/modules/contracts/entities/contract.entity.ts +++ b/src/modules/contracts/entities/contract.entity.ts @@ -25,7 +25,7 @@ export type ContractType = 'client' | 'subcontractor'; export type ContractStatus = 'draft' | 'review' | 'approved' | 'active' | 'completed' | 'terminated'; export type ClientContractType = 'desarrollo' | 'llave_en_mano' | 'administracion'; -@Entity({ schema: 'contracts', name: 'contracts' }) +@Entity({ schema: 'construction', name: 'contratos' }) @Index(['tenantId', 'contractNumber'], { unique: true }) export class Contract { @PrimaryGeneratedColumn('uuid') diff --git a/src/modules/contracts/entities/index.ts b/src/modules/contracts/entities/index.ts index 289d628..1ca2f4f 100644 --- a/src/modules/contracts/entities/index.ts +++ b/src/modules/contracts/entities/index.ts @@ -8,3 +8,4 @@ export * from './contract.entity'; export * from './subcontractor.entity'; export * from './contract-addendum.entity'; +export * from './contract-partida.entity'; diff --git a/src/modules/contracts/entities/subcontractor.entity.ts b/src/modules/contracts/entities/subcontractor.entity.ts index 89dabf3..34652e7 100644 --- a/src/modules/contracts/entities/subcontractor.entity.ts +++ b/src/modules/contracts/entities/subcontractor.entity.ts @@ -22,7 +22,7 @@ import { User } from '../../core/entities/user.entity'; export type SubcontractorSpecialty = 'cimentacion' | 'estructura' | 'instalaciones_electricas' | 'instalaciones_hidraulicas' | 'acabados' | 'urbanizacion' | 'carpinteria' | 'herreria' | 'otros'; export type SubcontractorStatus = 'active' | 'inactive' | 'blacklisted'; -@Entity({ schema: 'contracts', name: 'subcontractors' }) +@Entity({ schema: 'construction', name: 'subcontratistas' }) @Index(['tenantId', 'code'], { unique: true }) @Index(['tenantId', 'rfc'], { unique: true }) export class Subcontractor { diff --git a/src/modules/contracts/services/contract.service.ts b/src/modules/contracts/services/contract.service.ts index 1a197aa..303b94d 100644 --- a/src/modules/contracts/services/contract.service.ts +++ b/src/modules/contracts/services/contract.service.ts @@ -9,7 +9,11 @@ import { Repository, FindOptionsWhere, LessThan } from 'typeorm'; import { Contract, ContractStatus, ContractType } from '../entities/contract.entity'; import { ContractAddendum } from '../entities/contract-addendum.entity'; -import { ServiceContext, PaginatedResult } from '../../../shared/services/base.service'; + +interface ServiceContext { + tenantId: string; + userId?: string; +} export interface CreateContractDto { projectId?: string; @@ -77,7 +81,7 @@ export class ContractService { filters: ContractFilters = {}, page: number = 1, limit: number = 20 - ): Promise> { + ): Promise<{ data: Contract[]; total: number; page: number; limit: number }> { const skip = (page - 1) * limit; const queryBuilder = this.contractRepository @@ -126,15 +130,7 @@ export class ContractService { const [data, total] = await queryBuilder.getManyAndCount(); - return { - data, - meta: { - total, - page, - limit, - totalPages: Math.ceil(total / limit), - }, - }; + return { data, total, page, limit }; } async findById(ctx: ServiceContext, id: string): Promise { diff --git a/src/modules/contracts/services/subcontractor.service.ts b/src/modules/contracts/services/subcontractor.service.ts index eea8d86..fc17cb4 100644 --- a/src/modules/contracts/services/subcontractor.service.ts +++ b/src/modules/contracts/services/subcontractor.service.ts @@ -8,7 +8,11 @@ import { Repository, FindOptionsWhere } from 'typeorm'; import { Subcontractor, SubcontractorStatus, SubcontractorSpecialty } from '../entities/subcontractor.entity'; -import { ServiceContext, PaginatedResult } from '../../../shared/services/base.service'; + +interface ServiceContext { + tenantId: string; + userId?: string; +} export interface CreateSubcontractorDto { businessName: string; @@ -63,7 +67,7 @@ export class SubcontractorService { filters: SubcontractorFilters = {}, page: number = 1, limit: number = 20 - ): Promise> { + ): Promise<{ data: Subcontractor[]; total: number; page: number; limit: number }> { const skip = (page - 1) * limit; const queryBuilder = this.subcontractorRepository @@ -98,15 +102,7 @@ export class SubcontractorService { const [data, total] = await queryBuilder.getManyAndCount(); - return { - data, - meta: { - total, - page, - limit, - totalPages: Math.ceil(total / limit), - }, - }; + return { data, total, page, limit }; } async findById(ctx: ServiceContext, id: string): Promise {