npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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 CbmTaxIrbpnrRepository en 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:

  1. Fork el repositorio
  2. Crear una rama para la nueva funcionalidad
  3. Implementar los cambios siguiendo los patrones establecidos
  4. Agregar pruebas unitarias si es necesario
  5. 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