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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@cbm-common/deposit-cheque-repository

v0.0.1

Published

Repositorio Angular para la gestión completa de depósitos de cheques en sistemas financieros. Implementa operaciones CRUD, consultas paginadas y generación de asientos contables con integración completa al sistema CBM.

Readme

Deposit Cheque Repository

Repositorio Angular para la gestión completa de depósitos de cheques en sistemas financieros. Implementa operaciones CRUD, consultas paginadas y generación de asientos contables con integración completa al sistema CBM.

📦 Instalación

npm install @cbm-common/deposit-cheque-repository

⚙️ Configuración

Configuración del Módulo

El módulo debe configurarse en el módulo raíz de la aplicación:

import { CbmDepositChequeModule } from '@cbm-common/deposit-cheque-repository';

@NgModule({
  imports: [
    CbmDepositChequeModule.forRoot({
      baseUrl: 'https://api.cbm.com/deposit-cheques'
    })
  ]
})
export class AppModule {}

Configuración Standalone

Para aplicaciones standalone, configura el módulo en el bootstrap:

import { CbmDepositChequeModule } from '@cbm-common/deposit-cheque-repository';

bootstrapApplication(AppComponent, {
  providers: [
    CbmDepositChequeModule.forRoot({
      baseUrl: 'https://api.cbm.com/deposit-cheques'
    })
  ]
});

🎯 Inyección de Dependencias

Inyección del Servicio

import { CbmDepositChequeService } from '@cbm-common/deposit-cheque-repository';

@Component({
  selector: 'app-deposit-cheque-manager',
  standalone: true,
  imports: [CbmDepositChequeService]
})
export class DepositChequeManagerComponent {
  constructor(private depositChequeService: CbmDepositChequeService) {}
}

Inyección del Repositorio

import { CbmDepositChequeRepository } from '@cbm-common/deposit-cheque-repository';

@Component({
  selector: 'app-deposit-cheque-list',
  standalone: true,
  imports: [CbmDepositChequeRepository]
})
export class DepositChequeListComponent {
  constructor(private depositChequeRepo: CbmDepositChequeRepository) {}
}

🏗️ Arquitectura del Repositorio

Patrón de Diseño

El repositorio sigue el patrón Repository Pattern con Dependency Injection:

CbmDepositChequeModule
├── ICbmDepositChequeModuleConfig (configuración)
├── CbmDepositChequeService (implementa ICbmDepositChequeRepository)
├── CbmDepositChequeRepository (wrapper del service)
├── CbmDepositChequeModel (modelos de datos)
└── HttpClient (cliente HTTP)

Interfaz del Repositorio

export interface ICbmDepositChequeRepository {
  list(params: CbmDepositChequeModel.ListParams): Observable<CbmDepositChequeModel.ListResponse>;
  getOne(id: string): Observable<CbmDepositChequeModel.GetOneResponse>;
  save(data: CbmDepositChequeModel.SaveBody): Observable<CbmDepositChequeModel.ConfirmResponse>;
  generateOrRegenerateSeat(id: string): Observable<CbmDepositChequeModel.ConfirmResponse>;
}

📊 Operaciones Disponibles

Listado de Depósitos

// Listado paginado con filtros
list(params: {
  page: number;           // Página actual
  size: number;           // Tamaño de página
  document_number?: string; // Número de documento
  bank_name?: string;     // Nombre del banco
  operation_number?: string; // Número de operación
  category_id?: string;   // ID de categoría
  date_begin?: number;    // Fecha inicio (timestamp)
  date_end?: number;      // Fecha fin (timestamp)
  enabled?: boolean;      // Estado activo/inactivo
}): Observable<ListResponse>

Obtener Depósito Individual

// Obtener un depósito específico por ID
getOne(id: string): Observable<GetOneResponse>

Crear Nuevo Depósito

// Crear un nuevo depósito de cheque
save(data: SaveBody): Observable<ConfirmResponse>

Generar/Regenerar Asiento

// Generar o regenerar asiento contable
generateOrRegenerateSeat(id: string): Observable<ConfirmResponse>

📋 Modelos de Datos

ListResponse.Item

Información completa de un depósito de cheque:

interface Item {
  _id: string;
  company_id: string;
  company_branch_id: string;

  // Información de la empresa
  company_NIF: string;
  company_address: string;
  company_trade_name: string;
  company_business_name: string;

  // Información de la sucursal
  company_branch_identification_number: string;
  company_branch_trade_name: string;
  company_branch_logo: string;
  company_branch_address: string;
  company_branch_email: string;
  company_branch_cellphone: string;
  company_branch_phone: string;

  // Información bancaria
  financials_bank_id: string;
  financials_bank_name: string;
  financials_bank_account_number: string;

  // Información del depósito
  cost_center_id: string;
  document_nomenclature: string;
  document_number: string;
  total_payment: number;
  deposit_date: number;
  date: number;
  operation_number: string;
  enabled: boolean;
}

SaveBody

Datos para crear un nuevo depósito:

interface SaveBody {
  company_branch_id: string;
  financials_bank_id: string;
  cost_center_id: string;
  document_number: string;
  total_payment: number;
  deposit_date: number;
  operation_number: string;
  // ... otros campos según la API
}

🚀 Ejemplos de Uso

Ejemplo Básico: Listado de Depósitos

import { CbmDepositChequeService } from '@cbm-common/deposit-cheque-repository';
import { CbmDepositChequeModel } from '@cbm-common/deposit-cheque-repository';

@Component({
  selector: 'app-deposit-cheque-list',
  standalone: true,
  template: `
    <div class="deposit-list">
      <h2>Depósitos de Cheques</h2>

      <div class="filters">
        <input [(ngModel)]="filters.document_number" placeholder="Número de documento">
        <input [(ngModel)]="filters.bank_name" placeholder="Nombre del banco">
        <button (click)="loadDeposits()">Buscar</button>
      </div>

      <div class="table-container">
        <table>
          <thead>
            <tr>
              <th>Número Documento</th>
              <th>Banco</th>
              <th>Monto Total</th>
              <th>Fecha Depósito</th>
              <th>Estado</th>
              <th>Acciones</th>
            </tr>
          </thead>
          <tbody>
            <tr *ngFor="let deposit of deposits">
              <td>{{ deposit.document_number }}</td>
              <td>{{ deposit.financials_bank_name }}</td>
              <td>{{ deposit.total_payment | currency }}</td>
              <td>{{ deposit.deposit_date | date:'dd/MM/yyyy' }}</td>
              <td>
                <span [class]="'status ' + (deposit.enabled ? 'active' : 'inactive')">
                  {{ deposit.enabled ? 'Activo' : 'Inactivo' }}
                </span>
              </td>
              <td>
                <button (click)="viewDeposit(deposit._id)">Ver</button>
                <button (click)="generateSeat(deposit._id)">Generar Asiento</button>
              </td>
            </tr>
          </tbody>
        </table>
      </div>

      <div class="pagination" *ngIf="totalPages > 1">
        <button [disabled]="currentPage === 1" (click)="changePage(currentPage - 1)">
          Anterior
        </button>
        <span>Página {{ currentPage }} de {{ totalPages }}</span>
        <button [disabled]="currentPage === totalPages" (click)="changePage(currentPage + 1)">
          Siguiente
        </button>
      </div>
    </div>
  `,
  styles: [`
    .deposit-list { padding: 20px; }
    .filters { display: flex; gap: 10px; margin-bottom: 20px; }
    .table-container { overflow-x: auto; }
    table { width: 100%; border-collapse: collapse; }
    th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
    .status.active { color: green; }
    .status.inactive { color: red; }
    .pagination { display: flex; justify-content: center; align-items: center; gap: 10px; margin-top: 20px; }
  `]
})
export class DepositChequeListComponent implements OnInit {
  deposits: CbmDepositChequeModel.ListResponse.Item[] = [];
  currentPage = 1;
  pageSize = 10;
  totalPages = 0;

  filters: Partial<CbmDepositChequeModel.ListParams> = {
    document_number: '',
    bank_name: ''
  };

  constructor(private depositChequeService: CbmDepositChequeService) {}

  ngOnInit() {
    this.loadDeposits();
  }

  loadDeposits() {
    const params: CbmDepositChequeModel.ListParams = {
      page: this.currentPage,
      size: this.pageSize,
      ...this.filters
    };

    this.depositChequeService.list(params).subscribe({
      next: (response) => {
        this.deposits = response.items;
        this.totalPages = response.pages;
      },
      error: (error) => {
        console.error('Error al cargar depósitos:', error);
      }
    });
  }

  changePage(page: number) {
    this.currentPage = page;
    this.loadDeposits();
  }

  viewDeposit(id: string) {
    this.depositChequeService.getOne(id).subscribe({
      next: (deposit) => {
        console.log('Depósito:', deposit);
        // Mostrar modal o navegar a detalle
      }
    });
  }

  generateSeat(id: string) {
    this.depositChequeService.generateOrRegenerateSeat(id).subscribe({
      next: (response) => {
        console.log('Asiento generado:', response);
        // Mostrar mensaje de éxito
      },
      error: (error) => {
        console.error('Error al generar asiento:', error);
      }
    });
  }
}

Ejemplo con Formulario de Creación

import { ReactiveFormsModule } from '@angular/forms';
import { CbmDepositChequeService } from '@cbm-common/deposit-cheque-repository';

@Component({
  selector: 'app-deposit-cheque-form',
  standalone: true,
  imports: [ReactiveFormsModule, CbmDepositChequeService],
  template: `
    <form [formGroup]="depositForm" (ngSubmit)="onSubmit()">
      <h2>Crear Nuevo Depósito de Cheque</h2>

      <div class="form-group">
        <label for="documentNumber">Número de Documento</label>
        <input id="documentNumber" type="text" formControlName="document_number">
      </div>

      <div class="form-group">
        <label for="bankId">Banco</label>
        <select id="bankId" formControlName="financials_bank_id">
          <option *ngFor="let bank of banks" [value]="bank.id">
            {{ bank.name }}
          </option>
        </select>
      </div>

      <div class="form-group">
        <label for="totalPayment">Monto Total</label>
        <input id="totalPayment" type="number" formControlName="total_payment" step="0.01">
      </div>

      <div class="form-group">
        <label for="depositDate">Fecha de Depósito</label>
        <input id="depositDate" type="date" formControlName="deposit_date">
      </div>

      <div class="form-group">
        <label for="operationNumber">Número de Operación</label>
        <input id="operationNumber" type="text" formControlName="operation_number">
      </div>

      <div class="form-actions">
        <button type="button" (click)="onCancel()">Cancelar</button>
        <button type="submit" [disabled]="depositForm.invalid">Crear Depósito</button>
      </div>
    </form>
  `,
  styles: [`
    form { max-width: 500px; margin: 0 auto; }
    .form-group { margin-bottom: 15px; }
    label { display: block; margin-bottom: 5px; font-weight: bold; }
    input, select { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; }
    .form-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px; }
    button { padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }
    button[type="submit"] { background: #007bff; color: white; }
    button[type="button"] { background: #6c757d; color: white; }
    button:disabled { opacity: 0.6; cursor: not-allowed; }
  `]
})
export class DepositChequeFormComponent implements OnInit {
  depositForm!: FormGroup;
  banks: any[] = [];

  constructor(
    private fb: FormBuilder,
    private depositChequeService: CbmDepositChequeService
  ) {}

  ngOnInit() {
    this.initForm();
    this.loadBanks();
  }

  initForm() {
    this.depositForm = this.fb.group({
      company_branch_id: ['', Validators.required],
      financials_bank_id: ['', Validators.required],
      cost_center_id: ['', Validators.required],
      document_number: ['', Validators.required],
      total_payment: ['', [Validators.required, Validators.min(0)]],
      deposit_date: ['', Validators.required],
      operation_number: ['', Validators.required]
    });
  }

  loadBanks() {
    // Cargar lista de bancos desde servicio
    this.banks = [
      { id: '1', name: 'Banco Nacional' },
      { id: '2', name: 'Banco Internacional' }
    ];
  }

  onSubmit() {
    if (this.depositForm.valid) {
      const formData = this.depositForm.value;

      // Convertir fecha a timestamp
      formData.deposit_date = new Date(formData.deposit_date).getTime();

      this.depositChequeService.save(formData).subscribe({
        next: (response) => {
          console.log('Depósito creado:', response);
          // Resetear formulario y mostrar mensaje de éxito
          this.depositForm.reset();
        },
        error: (error) => {
          console.error('Error al crear depósito:', error);
        }
      });
    }
  }

  onCancel() {
    this.depositForm.reset();
  }
}

Ejemplo con Gestión de Estados

import { BehaviorSubject, combineLatest } from 'rxjs';
import { map, startWith } from 'rxjs/operators';

@Component({
  selector: 'app-deposit-cheque-dashboard',
  standalone: true,
  template: `
    <div class="dashboard">
      <div class="stats">
        <div class="stat-card">
          <h3>Total Depósitos</h3>
          <span class="stat-number">{{ totalDeposits$ | async }}</span>
        </div>

        <div class="stat-card">
          <h3>Monto Total</h3>
          <span class="stat-number">{{ totalAmount$ | async | currency }}</span>
        </div>

        <div class="stat-card">
          <h3>Depósitos Activos</h3>
          <span class="stat-number">{{ activeDeposits$ | async }}</span>
        </div>
      </div>

      <div class="recent-deposits">
        <h3>Depósitos Recientes</h3>
        <div class="deposit-item" *ngFor="let deposit of recentDeposits$ | async">
          <div class="deposit-info">
            <span class="document">{{ deposit.document_number }}</span>
            <span class="bank">{{ deposit.financials_bank_name }}</span>
          </div>
          <div class="deposit-amount">
            {{ deposit.total_payment | currency }}
          </div>
        </div>
      </div>
    </div>
  `
})
export class DepositChequeDashboardComponent implements OnInit {
  private depositsSubject = new BehaviorSubject<CbmDepositChequeModel.ListResponse.Item[]>([]);
  deposits$ = this.depositsSubject.asObservable();

  totalDeposits$ = this.deposits$.pipe(
    map(deposits => deposits.length)
  );

  totalAmount$ = this.deposits$.pipe(
    map(deposits => deposits.reduce((sum, deposit) => sum + deposit.total_payment, 0))
  );

  activeDeposits$ = this.deposits$.pipe(
    map(deposits => deposits.filter(deposit => deposit.enabled).length)
  );

  recentDeposits$ = this.deposits$.pipe(
    map(deposits => deposits.slice(0, 5))
  );

  constructor(private depositChequeService: CbmDepositChequeService) {}

  ngOnInit() {
    this.loadDeposits();
  }

  loadDeposits() {
    const params: CbmDepositChequeModel.ListParams = {
      page: 1,
      size: 100,
      enabled: true
    };

    this.depositChequeService.list(params).subscribe({
      next: (response) => {
        this.depositsSubject.next(response.items);
      },
      error: (error) => {
        console.error('Error al cargar depósitos:', error);
      }
    });
  }
}

Ejemplo con Integración RxJS Avanzada

import { debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
import { Subject } from 'rxjs';

@Component({
  selector: 'app-deposit-cheque-search',
  standalone: true,
  template: `
    <div class="search-container">
      <input
        type="text"
        placeholder="Buscar por número de documento o banco..."
        [formControl]="searchControl"
        class="search-input">

      <div class="search-results" *ngIf="searchResults$ | async as results">
        <div class="result-item" *ngFor="let result of results" (click)="selectDeposit(result)">
          <div class="result-info">
            <span class="document">{{ result.document_number }}</span>
            <span class="bank">{{ result.financials_bank_name }}</span>
          </div>
          <div class="result-amount">
            {{ result.total_payment | currency }}
          </div>
        </div>

        <div class="no-results" *ngIf="results.length === 0">
          No se encontraron depósitos
        </div>
      </div>
    </div>
  `,
  styles: [`
    .search-container { position: relative; }
    .search-input { width: 100%; padding: 12px; border: 1px solid #ddd; border-radius: 4px; }
    .search-results { position: absolute; top: 100%; left: 0; right: 0; background: white; border: 1px solid #ddd; border-radius: 4px; max-height: 300px; overflow-y: auto; z-index: 1000; }
    .result-item { padding: 12px; border-bottom: 1px solid #eee; cursor: pointer; display: flex; justify-content: space-between; }
    .result-item:hover { background: #f5f5f5; }
    .no-results { padding: 12px; text-align: center; color: #666; }
  `]
})
export class DepositChequeSearchComponent implements OnInit, OnDestroy {
  searchControl = new FormControl('');
  private searchSubject = new Subject<string>();
  private destroy$ = new Subject<void>();

  searchResults$ = this.searchSubject.pipe(
    debounceTime(300),
    distinctUntilChanged(),
    switchMap(term => {
      if (term.length < 3) return of([]);

      const params: CbmDepositChequeModel.ListParams = {
        page: 1,
        size: 10,
        document_number: term,
        bank_name: term
      };

      return this.depositChequeService.list(params).pipe(
        map(response => response.items),
        catchError(() => of([]))
      );
    })
  );

  constructor(private depositChequeService: CbmDepositChequeService) {}

  ngOnInit() {
    this.searchControl.valueChanges.pipe(
      takeUntil(this.destroy$)
    ).subscribe(value => {
      this.searchSubject.next(value || '');
    });
  }

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }

  selectDeposit(deposit: CbmDepositChequeModel.ListResponse.Item) {
    console.log('Depósito seleccionado:', deposit);
    // Emitir evento o navegar a detalle
  }
}

⚠️ Manejo de Errores

Errores de API

// Manejo de errores en operaciones
saveDeposit(depositData: CbmDepositChequeModel.SaveBody) {
  this.depositChequeService.save(depositData).subscribe({
    next: (response) => {
      if (response.success) {
        console.log('Depósito creado exitosamente');
        this.showSuccessMessage('Depósito creado correctamente');
      } else {
        console.error('Error en la respuesta:', response);
        this.showErrorMessage('Error al crear el depósito');
      }
    },
    error: (error) => {
      console.error('Error HTTP:', error);

      if (error.status === 400) {
        this.showErrorMessage('Datos inválidos. Verifique la información.');
      } else if (error.status === 401) {
        this.showErrorMessage('Sesión expirada. Inicie sesión nuevamente.');
      } else if (error.status === 403) {
        this.showErrorMessage('No tiene permisos para esta operación.');
      } else {
        this.showErrorMessage('Error interno del servidor.');
      }
    }
  });
}

Estados de Carga

// Gestión de estados de carga
export class DepositChequeListComponent {
  isLoading = false;
  deposits: CbmDepositChequeModel.ListResponse.Item[] = [];

  loadDeposits() {
    this.isLoading = true;

    const params: CbmDepositChequeModel.ListParams = {
      page: this.currentPage,
      size: this.pageSize
    };

    this.depositChequeService.list(params).subscribe({
      next: (response) => {
        this.deposits = response.items;
        this.isLoading = false;
      },
      error: (error) => {
        console.error('Error al cargar depósitos:', error);
        this.isLoading = false;
        this.showErrorMessage('Error al cargar la lista de depósitos');
      }
    });
  }
}

🔧 Configuración Avanzada

Configuración de Headers HTTP

// Configuración personalizada de HTTP
import { HTTP_INTERCEPTORS } from '@angular/common/http';

@NgModule({
  providers: [
    CbmDepositChequeModule.forRoot({
      baseUrl: 'https://api.cbm.com/deposit-cheques'
    }),
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthInterceptor,
      multi: true
    }
  ]
})
export class AppModule {}

Configuración de Timeouts

// Configuración de timeouts para operaciones largas
generateSeatWithTimeout(id: string) {
  return this.depositChequeService.generateOrRegenerateSeat(id).pipe(
    timeout(30000), // 30 segundos timeout
    catchError(error => {
      if (error.name === 'TimeoutError') {
        return throwError(() => new Error('La operación tomó demasiado tiempo'));
      }
      return throwError(() => error);
    })
  );
}

Reintentos Automáticos

// Implementar reintentos para operaciones fallidas
saveDepositWithRetry(depositData: CbmDepositChequeModel.SaveBody, maxRetries = 3) {
  return this.depositChequeService.save(depositData).pipe(
    retry({
      count: maxRetries,
      delay: (error, retryCount) => timer(retryCount * 1000)
    }),
    catchError(error => {
      console.error(`Falló después de ${maxRetries} intentos:`, error);
      return throwError(() => error);
    })
  );
}

📋 Dependencias

Peer Dependencies (Requeridas)

{
  "@angular/common": ">=20.1.5",
  "@angular/core": ">=20.1.5"
}

Dependencias Internas

{
  "tslib": "^2.3.0"
}

🛠️ Desarrollo

Estructura del Proyecto

deposit-cheque-repository/
├── src/
│   ├── lib/
│   │   ├── deposit-cheque.model.ts       # Modelos de datos
│   │   ├── deposit-cheque.module.ts      # Configuración del módulo
│   │   ├── deposit-cheque.service.ts     # Servicio HTTP
│   │   ├── deposit-cheque.repository.ts  # Interfaz del repositorio
│   │   └── index.ts                      # Exportaciones
│   └── public-api.ts                     # API pública
├── ng-package.json                       # Configuración empaquetado
├── package.json                          # Dependencias
└── README.md                             # Esta documentación

Construcción

# Construir la librería
ng build deposit-cheque-repository

# Construir en modo watch
ng build deposit-cheque-repository --watch

# Construir para producción
ng build deposit-cheque-repository --configuration production

Pruebas

# Ejecutar pruebas unitarias
ng test deposit-cheque-repository

# Ejecutar pruebas con coverage
ng test deposit-cheque-repository --code-coverage

# Pruebas end-to-end
ng e2e deposit-cheque-repository

🎯 Mejores Prácticas

1. Gestión de Memoria

// Limpiar suscripciones para evitar memory leaks
export class DepositChequeListComponent implements OnDestroy {
  private destroy$ = new Subject<void>();

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }

  loadDeposits() {
    this.depositChequeService.list(params).pipe(
      takeUntil(this.destroy$)
    ).subscribe({
      next: (response) => {
        this.deposits = response.items;
      }
    });
  }
}

2. Optimización de Rendimiento

// Usar OnPush change detection para mejor rendimiento
@Component({
  selector: 'app-deposit-cheque-list',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `...`
})
export class DepositChequeListComponent {
  deposits$ = this.depositChequeService.list(params).pipe(
    shareReplay(1) // Compartir la respuesta entre múltiples suscriptores
  );
}

3. Validación de Datos

// Validaciones personalizadas para depósitos
export class DepositValidators {
  static validDocumentNumber(control: AbstractControl): ValidationErrors | null {
    const value = control.value;
    if (!value) return null;

    // Validar formato de número de documento
    const documentPattern = /^[A-Z]{2}\d{8}$/;
    return documentPattern.test(value) ? null : { invalidDocumentNumber: true };
  }

  static validTotalPayment(control: AbstractControl): ValidationErrors | null {
    const value = control.value;
    if (!value) return null;

    return value > 0 ? null : { invalidTotalPayment: true };
  }
}

// Uso en formularios reactivos
this.depositForm = this.fb.group({
  document_number: ['', [Validators.required, DepositValidators.validDocumentNumber]],
  total_payment: ['', [Validators.required, DepositValidators.validTotalPayment]]
});

4. Logging y Monitoreo

// Servicio de logging para operaciones de depósitos
@Injectable({ providedIn: 'root' })
export class DepositLoggingService {
  logOperation(operation: string, data: any) {
    console.log(`[${new Date().toISOString()}] ${operation}:`, data);

    // Enviar a servicio de analytics
    this.analytics.trackEvent('deposit_operation', {
      operation,
      timestamp: Date.now(),
      data
    });
  }

  logError(operation: string, error: any) {
    console.error(`[${new Date().toISOString()}] Error in ${operation}:`, error);

    // Enviar a servicio de error tracking
    this.errorTracker.captureException(error, {
      tags: { operation, module: 'deposit-cheque' }
    });
  }
}

🤝 Contribución

  1. Fork el repositorio
  2. Crea una rama para tu feature (git checkout -b feature/nueva-funcionalidad)
  3. Commit tus cambios (git commit -am 'Agrega nueva funcionalidad')
  4. Push a la rama (git push origin feature/nueva-funcionalidad)
  5. Abre un PullRequest

📄 Licencia

Este proyecto está bajo la Licencia MIT - ver el archivo LICENSE para más detalles.

📞 Soporte

Para soporte técnico o reportes de bugs, contacta al equipo de desarrollo de CBM:

🔄 Changelog

v0.0.1

  • ✅ Módulo de configuración con forRoot pattern
  • ✅ Servicio que implementa interfaz del repositorio
  • ✅ Operaciones CRUD completas (list, getOne, save)
  • ✅ Generación/regeneración de asientos contables
  • ✅ Modelos TypeScript bien tipados
  • ✅ Integración completa con HttpClient
  • ✅ Documentación completa en español

Nota: Este repositorio está optimizado para sistemas financieros que requieren gestión completa de depósitos de cheques con integración bancaria y contable. Las operaciones incluyen validaciones de negocio y manejo robusto de errores.