@cbm-common/tax-irbpnr-repository
v0.0.1
Published
Biblioteca Angular especializada en la gestión de información del Impuesto a la Renta Bruta de las Personas Naturales y Residentes (IRBPNR) por país. Proporciona una API simple y eficiente para acceder a los datos fiscales relacionados con el IRBPNR organ
Readme
Tax IRBPNR Repository
Biblioteca Angular especializada en la gestión de información del Impuesto a la Renta Bruta de las Personas Naturales y Residentes (IRBPNR) por país. Proporciona una API simple y eficiente para acceder a los datos fiscales relacionados con el IRBPNR organizados por jurisdicción territorial.
📋 Características Principales
- ✅ Gestión de IRBPNR por País: Acceso a información fiscal del Impuesto a la Renta Bruta
- ✅ Datos Estructurados: Valores porcentuales, códigos y metadatos por país
- ✅ Arquitectura Moderna: Basada en Angular 20.1.5 con inyección de dependencias
- ✅ Patrón Repository: Separación clara entre lógica de negocio y acceso a datos
- ✅ Configuración Simplificada: Setup rápido con método
forRoot() - ✅ TypeScript Nativo: Interfaces tipadas para mayor seguridad y mantenibilidad
🚀 Instalación
npm install @cbm-common/tax-irbpnr-repository⚙️ Configuración
1. Importar el Módulo
import { CbmTaxIrbpnrModule } from '@cbm-common/tax-irbpnr-repository';
@NgModule({
imports: [
CbmTaxIrbpnrModule.forRoot({
baseUrl: 'https://api.cbm.com/tax-irbpnr'
})
]
})
export class AppModule { }2. Configuración Standalone (Angular 20+)
import { CbmTaxIrbpnrModule } from '@cbm-common/tax-irbpnr-repository';
@Component({
standalone: true,
imports: [CbmTaxIrbpnrModule.forRoot({
baseUrl: 'https://api.cbm.com/tax-irbpnr'
})]
})
export class AppComponent { }📚 API Reference
Interfaz del Repositorio
interface ICbmTaxIrbpnrRepository {
// Obtener lista de IRBPNR por países
list(): Observable<CbmTaxIrbpnrModel.ListResponse>;
}💡 Uso Básico
Inyección del Servicio
import { CbmTaxIrbpnrRepository } from '@cbm-common/tax-irbpnr-repository';
@Component({
selector: 'app-tax-irbpnr-manager'
})
export class TaxIrbpnrManagerComponent {
irbpnrData: CbmTaxIrbpnrModel.ListResponse.Data[] = [];
constructor(private taxIrbpnrRepository: CbmTaxIrbpnrRepository) {
this.loadIrbpnrData();
}
loadIrbpnrData() {
this.taxIrbpnrRepository.list().subscribe({
next: (response) => {
if (response.success) {
this.irbpnrData = response.data;
console.log('Datos IRBPNR cargados:', this.irbpnrData);
}
},
error: (error) => {
console.error('Error al cargar datos IRBPNR:', error);
}
});
}
}Procesamiento de Datos IRBPNR
@Component({
selector: 'app-tax-calculator'
})
export class TaxCalculatorComponent {
constructor(private taxIrbpnrRepository: CbmTaxIrbpnrRepository) {}
calculateIrbpnrByCountry(countryId: string, baseAmount: number) {
this.taxIrbpnrRepository.list().subscribe({
next: (response) => {
if (response.success) {
const countryTax = response.data.find(
item => item.country_id === countryId
);
if (countryTax) {
const taxAmount = (baseAmount * countryTax.value) / 100;
console.log(`IRBPNR ${countryTax.value}%:`, taxAmount);
console.log(`Monto base: ${baseAmount}, Impuesto: ${taxAmount}`);
} else {
console.warn('País no encontrado en datos IRBPNR');
}
}
},
error: (error) => console.error('Error en cálculo IRBPNR:', error)
});
}
}📊 Modelos de Datos
Respuesta de Lista
interface ListResponse {
success: boolean; // Indicador de éxito de la operación
data: ListResponse.Data[]; // Array de datos IRBPNR
}
interface ListResponse.Data {
_id: string; // ID único del registro IRBPNR
country_id: string; // ID del país
value: number; // Valor porcentual del IRBPNR
code: string; // Código del impuesto
created_at?: number; // Fecha de creación (timestamp)
created_user?: string; // Usuario que creó el registro
updated_at?: number; // Fecha de actualización (timestamp)
updated_user?: string; // Usuario que actualizó el registro
country?: string; // Nombre del país (opcional)
}Ejemplo de Datos
{
"success": true,
"data": [
{
"_id": "64f1a2b3c4d5e6f7g8h9i0j1",
"country_id": "ecuador",
"value": 2.75,
"code": "IRBPNR-EC",
"created_at": 1694000000000,
"created_user": "admin",
"updated_at": 1694000000000,
"updated_user": "admin",
"country": "Ecuador"
},
{
"_id": "64f1a2b3c4d5e6f7g8h9i0j2",
"country_id": "colombia",
"value": 3.50,
"code": "IRBPNR-CO",
"created_at": 1694000000000,
"created_user": "admin",
"country": "Colombia"
}
]
}🔍 Casos de Uso Comunes
1. Sistema de Cálculo Fiscal
@Component({
selector: 'app-fiscal-calculator'
})
export class FiscalCalculatorComponent {
irbpnrRates: Map<string, number> = new Map();
constructor(private taxIrbpnrRepository: CbmTaxIrbpnrRepository) {
this.loadIrbpnrRates();
}
private loadIrbpnrRates() {
this.taxIrbpnrRepository.list().subscribe({
next: (response) => {
if (response.success) {
response.data.forEach(item => {
this.irbpnrRates.set(item.country_id, item.value);
});
}
}
});
}
calculateTax(countryId: string, amount: number): number {
const rate = this.irbpnrRates.get(countryId) || 0;
return (amount * rate) / 100;
}
getTaxInfo(countryId: string) {
return this.taxIrbpnrRepository.list().pipe(
map(response => response.data.find(item => item.country_id === countryId)),
filter(item => !!item)
);
}
}2. Dashboard de Información Fiscal
@Component({
selector: 'app-tax-dashboard'
})
export class TaxDashboardComponent {
irbpnrSummary = {
totalCountries: 0,
averageRate: 0,
highestRate: { country: '', value: 0 },
lowestRate: { country: '', value: Infinity }
};
constructor(private taxIrbpnrRepository: CbmTaxIrbpnrRepository) {
this.loadDashboardData();
}
loadDashboardData() {
this.taxIrbpnrRepository.list().subscribe({
next: (response) => {
if (response.success) {
this.calculateSummary(response.data);
}
}
});
}
private calculateSummary(data: CbmTaxIrbpnrModel.ListResponse.Data[]) {
this.irbpnrSummary.totalCountries = data.length;
const rates = data.map(item => item.value);
this.irbpnrSummary.averageRate = rates.reduce((a, b) => a + b, 0) / rates.length;
data.forEach(item => {
if (item.value > this.irbpnrSummary.highestRate.value) {
this.irbpnrSummary.highestRate = { country: item.country || item.country_id, value: item.value };
}
if (item.value < this.irbpnrSummary.lowestRate.value) {
this.irbpnrSummary.lowestRate = { country: item.country || item.country_id, value: item.value };
}
});
}
}3. Selector de País con Información Fiscal
@Component({
selector: 'app-country-selector'
})
export class CountrySelectorComponent {
countries: CbmTaxIrbpnrModel.ListResponse.Data[] = [];
selectedCountry: CbmTaxIrbpnrModel.ListResponse.Data | null = null;
constructor(private taxIrbpnrRepository: CbmTaxIrbpnrRepository) {
this.loadCountries();
}
loadCountries() {
this.taxIrbpnrRepository.list().subscribe({
next: (response) => {
if (response.success) {
this.countries = response.data.sort((a, b) =>
(a.country || a.country_id).localeCompare(b.country || b.country_id)
);
}
}
});
}
onCountrySelect(country: CbmTaxIrbpnrModel.ListResponse.Data) {
this.selectedCountry = country;
console.log(`País seleccionado: ${country.country || country.country_id}`);
console.log(`Tasa IRBPNR: ${country.value}%`);
}
getFormattedRate(country: CbmTaxIrbpnrModel.ListResponse.Data): string {
return `${country.value.toFixed(2)}%`;
}
}🏗️ Arquitectura y Patrones
Patrón Repository
La biblioteca implementa el patrón Repository para mantener la separación entre la lógica de negocio y el acceso a datos:
// Interfaz del repositorio
export interface ICbmTaxIrbpnrRepository {
list(): Observable<CbmTaxIrbpnrModel.ListResponse>;
}
// Implementación del servicio
@Injectable({ providedIn: 'root' })
export class CbmTaxIrbpnrService implements ICbmTaxIrbpnrRepository {
constructor(
private readonly http: HttpClient,
@Inject(TAX_IRBPNR_MODULE_CONFIG) private readonly config: ICbmTaxIrbpnrModuleConfig
) {}
list(): Observable<CbmTaxIrbpnrModel.ListResponse> {
return this.http.get<CbmTaxIrbpnrModel.ListResponse>(this.config.baseUrl);
}
}
// Wrapper del repositorio
@Injectable({ providedIn: 'root' })
export class CbmTaxIrbpnrRepository implements ICbmTaxIrbpnrRepository {
constructor(private service: CbmTaxIrbpnrService) {}
list(): Observable<CbmTaxIrbpnrModel.ListResponse> {
return this.service.list();
}
}Configuración Centralizada
// Configuración del módulo
@NgModule({
imports: [
CbmTaxIrbpnrModule.forRoot({
baseUrl: environment.apiUrl + '/tax-irbpnr'
})
]
})
export class AppModule {}🔧 Mejores Prácticas
Manejo de Errores
@Component({
selector: 'app-safe-tax-handler'
})
export class SafeTaxHandlerComponent {
constructor(private taxIrbpnrRepository: CbmTaxIrbpnrRepository) {}
safeLoadTaxData() {
this.taxIrbpnrRepository.list().subscribe({
next: (response) => {
if (response.success && response.data) {
this.processTaxData(response.data);
} else {
this.showErrorMessage('Respuesta inválida del servidor');
}
},
error: (error) => {
if (error.status === 404) {
this.showErrorMessage('Servicio de impuestos no disponible');
} else if (error.status === 500) {
this.showErrorMessage('Error interno del servidor');
} else {
this.showErrorMessage('Error de conexión');
}
}
});
}
private processTaxData(data: CbmTaxIrbpnrModel.ListResponse.Data[]) {
// Procesar datos de manera segura
data.forEach(item => {
if (item.value >= 0 && item.value <= 100) {
// Procesar tasa válida
} else {
console.warn(`Tasa inválida para ${item.country_id}: ${item.value}`);
}
});
}
private showErrorMessage(message: string) {
// Mostrar mensaje de error al usuario
}
}Caché de Datos Fiscales
@Injectable({ providedIn: 'root' })
export class TaxCacheService {
private cache = new Map<string, CbmTaxIrbpnrModel.ListResponse.Data[]>();
private readonly CACHE_DURATION = 24 * 60 * 60 * 1000; // 24 horas
constructor(private taxIrbpnrRepository: CbmTaxIrbpnrRepository) {}
getTaxData(forceRefresh = false): Observable<CbmTaxIrbpnrModel.ListResponse.Data[]> {
const cacheKey = 'irbpnr-data';
const cached = this.cache.get(cacheKey);
if (cached && !forceRefresh && !this.isCacheExpired(cached)) {
return of(cached);
}
return this.taxIrbpnrRepository.list().pipe(
map(response => {
if (response.success) {
this.cache.set(cacheKey, response.data);
return response.data;
}
throw new Error('Error al obtener datos fiscales');
})
);
}
private isCacheExpired(data: CbmTaxIrbpnrModel.ListResponse.Data[]): boolean {
if (data.length === 0) return true;
const oldestRecord = Math.min(...data.map(item => item.updated_at || 0));
return Date.now() - oldestRecord > this.CACHE_DURATION;
}
}Validación de Datos
@Component({
selector: 'app-tax-validator'
})
export class TaxValidatorComponent {
constructor(private taxIrbpnrRepository: CbmTaxIrbpnrRepository) {}
validateTaxData(): Observable<boolean> {
return this.taxIrbpnrRepository.list().pipe(
map(response => {
if (!response.success || !response.data) {
return false;
}
return response.data.every(item => {
return item._id &&
item.country_id &&
typeof item.value === 'number' &&
item.value >= 0 &&
item.value <= 100 &&
item.code;
});
}),
catchError(() => of(false))
);
}
getValidCountries(): Observable<CbmTaxIrbpnrModel.ListResponse.Data[]> {
return this.taxIrbpnrRepository.list().pipe(
map(response => {
if (!response.success) return [];
return response.data.filter(item =>
item.country_id &&
typeof item.value === 'number' &&
item.value >= 0 &&
item.value <= 100
);
})
);
}
}📋 Lista de Verificación para Implementación
- [ ] ✅ Configurar el módulo
CbmTaxIrbpnrModule.forRoot()en el AppModule - [ ] ✅ Inyectar
CbmTaxIrbpnrRepositoryen los componentes que lo necesiten - [ ] ✅ Implementar manejo de errores para la operación de listado
- [ ] ✅ Validar que los datos fiscales sean correctos antes de usarlos
- [ ] ✅ Implementar indicadores de carga durante las operaciones
- [ ] ✅ Manejar estados de error y respuestas no exitosas
- [ ] ✅ Considerar implementar caché para datos fiscales (cambian infrequentemente)
- [ ] ✅ Probar la funcionalidad en diferentes navegadores
- [ ] ✅ Verificar funcionamiento con conexiones lentas
- [ ] ✅ Documentar casos de uso específicos de la aplicación
🔗 Dependencias
{
"peerDependencies": {
"@angular/common": "20.1.5",
"@angular/core": "20.1.5",
"@angular/common/http": "20.1.5"
},
"dependencies": {
"tslib": "2.3.0"
}
}📝 Notas de Versión
v0.0.1
- ✅ Implementación inicial del repositorio de IRBPNR
- ✅ Soporte para listado de datos fiscales por país
- ✅ Arquitectura basada en patrón Repository
- ✅ Configuración simplificada con
forRoot() - ✅ Compatibilidad con Angular 20.1.5
- ✅ Interfaces TypeScript tipadas
- ✅ Documentación completa en español
🤝 Contribución
Para contribuir a esta biblioteca:
- Fork el repositorio
- Crear una rama para la nueva funcionalidad
- Implementar los cambios siguiendo los patrones establecidos
- Agregar pruebas unitarias si es necesario
- Enviar un Pull Request con descripción detallada
📞 Soporte
Para soporte técnico o consultas sobre el uso de la biblioteca, contactar al equipo de desarrollo de CBM.
CBM (Contabilidad y Facturación Moderna) - Repositorio de IRBPNR v0.0.1
