import { Repository } from 'typeorm'; import { AppDataSource } from '../../config/typeorm.js'; import { State } from './entities/state.entity.js'; import { NotFoundError } from '../../shared/errors/index.js'; import { logger } from '../../shared/utils/logger.js'; export interface CreateStateDto { countryId: string; code: string; name: string; timezone?: string; isActive?: boolean; } export interface UpdateStateDto { name?: string; timezone?: string; isActive?: boolean; } export interface StateFilter { countryId?: string; countryCode?: string; isActive?: boolean; } class StatesService { private repository: Repository; constructor() { this.repository = AppDataSource.getRepository(State); } async findAll(filter: StateFilter = {}): Promise { logger.debug('Finding all states', { filter }); const query = this.repository .createQueryBuilder('state') .leftJoinAndSelect('state.country', 'country'); if (filter.countryId) { query.andWhere('state.countryId = :countryId', { countryId: filter.countryId }); } if (filter.countryCode) { query.andWhere('country.code = :countryCode', { countryCode: filter.countryCode.toUpperCase() }); } if (filter.isActive !== undefined) { query.andWhere('state.isActive = :isActive', { isActive: filter.isActive }); } query.orderBy('state.name', 'ASC'); return query.getMany(); } async findById(id: string): Promise { logger.debug('Finding state by id', { id }); const state = await this.repository.findOne({ where: { id }, relations: ['country'], }); if (!state) { throw new NotFoundError('Estado no encontrado'); } return state; } async findByCode(countryId: string, code: string): Promise { logger.debug('Finding state by code', { countryId, code }); return this.repository.findOne({ where: { countryId, code: code.toUpperCase() }, relations: ['country'], }); } async findByCountry(countryId: string): Promise { logger.debug('Finding states by country', { countryId }); return this.repository.find({ where: { countryId, isActive: true }, relations: ['country'], order: { name: 'ASC' }, }); } async findByCountryCode(countryCode: string): Promise { logger.debug('Finding states by country code', { countryCode }); return this.repository .createQueryBuilder('state') .leftJoinAndSelect('state.country', 'country') .where('country.code = :countryCode', { countryCode: countryCode.toUpperCase() }) .andWhere('state.isActive = :isActive', { isActive: true }) .orderBy('state.name', 'ASC') .getMany(); } async create(dto: CreateStateDto): Promise { logger.info('Creating state', { dto }); // Check if state already exists for this country const existing = await this.findByCode(dto.countryId, dto.code); if (existing) { throw new Error(`Estado con código ${dto.code} ya existe para este país`); } const state = this.repository.create({ ...dto, code: dto.code.toUpperCase(), isActive: dto.isActive ?? true, }); return this.repository.save(state); } async update(id: string, dto: UpdateStateDto): Promise { logger.info('Updating state', { id, dto }); const state = await this.findById(id); Object.assign(state, dto); return this.repository.save(state); } async delete(id: string): Promise { logger.info('Deleting state', { id }); const state = await this.findById(id); await this.repository.remove(state); } async setActive(id: string, isActive: boolean): Promise { logger.info('Setting state active status', { id, isActive }); const state = await this.findById(id); state.isActive = isActive; return this.repository.save(state); } } export const statesService = new StatesService();