erp-core-backend-v2/src/modules/core/currencies.service.ts

119 lines
3.1 KiB
TypeScript

import { Repository } from 'typeorm';
import { AppDataSource } from '../../config/typeorm.js';
import { Currency } from './entities/currency.entity.js';
import { NotFoundError, ConflictError } from '../../shared/errors/index.js';
import { logger } from '../../shared/utils/logger.js';
export interface CreateCurrencyDto {
code: string;
name: string;
symbol: string;
decimal_places?: number;
decimals?: number; // Accept camelCase too
}
export interface UpdateCurrencyDto {
name?: string;
symbol?: string;
decimal_places?: number;
decimals?: number; // Accept camelCase too
active?: boolean;
}
class CurrenciesService {
private repository: Repository<Currency>;
constructor() {
this.repository = AppDataSource.getRepository(Currency);
}
async findAll(activeOnly: boolean = false): Promise<Currency[]> {
logger.debug('Finding all currencies', { activeOnly });
const queryBuilder = this.repository
.createQueryBuilder('currency')
.orderBy('currency.code', 'ASC');
if (activeOnly) {
queryBuilder.where('currency.active = :active', { active: true });
}
return queryBuilder.getMany();
}
async findById(id: string): Promise<Currency> {
logger.debug('Finding currency by id', { id });
const currency = await this.repository.findOne({
where: { id },
});
if (!currency) {
throw new NotFoundError('Moneda no encontrada');
}
return currency;
}
async findByCode(code: string): Promise<Currency | null> {
logger.debug('Finding currency by code', { code });
return this.repository.findOne({
where: { code: code.toUpperCase() },
});
}
async create(dto: CreateCurrencyDto): Promise<Currency> {
logger.debug('Creating currency', { code: dto.code });
const existing = await this.findByCode(dto.code);
if (existing) {
throw new ConflictError(`Ya existe una moneda con código ${dto.code}`);
}
// Accept both snake_case and camelCase
const decimals = dto.decimal_places ?? dto.decimals ?? 2;
const currency = this.repository.create({
code: dto.code.toUpperCase(),
name: dto.name,
symbol: dto.symbol,
decimals,
});
const saved = await this.repository.save(currency);
logger.info('Currency created', { id: saved.id, code: saved.code });
return saved;
}
async update(id: string, dto: UpdateCurrencyDto): Promise<Currency> {
logger.debug('Updating currency', { id });
const currency = await this.findById(id);
// Accept both snake_case and camelCase
const decimals = dto.decimal_places ?? dto.decimals;
if (dto.name !== undefined) {
currency.name = dto.name;
}
if (dto.symbol !== undefined) {
currency.symbol = dto.symbol;
}
if (decimals !== undefined) {
currency.decimals = decimals;
}
if (dto.active !== undefined) {
currency.active = dto.active;
}
const updated = await this.repository.save(currency);
logger.info('Currency updated', { id: updated.id, code: updated.code });
return updated;
}
}
export const currenciesService = new CurrenciesService();