Skip to main content

Overview

The Prestamo interface represents a book loan in the virtual library system. It tracks loan requests, approvals, rejections, and returns.

Interface Definition

import { Libro } from './libro';

export interface Prestamo {
  id: number;
  fechaSolicitud: string;
  fechaDevolucion?: string;
  estado: 'PENDIENTE' | 'APROBADO' | 'RECHAZADO';
  libro: Libro;
  usuario: any; // Usuario completo desde Spring Boot
}

Properties

Basic Properties

id
number
required
Unique identifier for the loan. Auto-generated by the backend.
fechaSolicitud
string
required
The date and time when the loan was requested. Typically in ISO 8601 format (e.g., "2024-03-15T10:30:00").
fechaDevolucion
string
Optional return date for the book. Set when the book is returned or when an approved loan has a due date.
estado
'PENDIENTE' | 'APROBADO' | 'RECHAZADO'
required
The current status of the loan request:
  • PENDIENTE: Loan request is pending approval
  • APROBADO: Loan has been approved by an administrator
  • RECHAZADO: Loan request has been rejected

Relationships

libro
Libro
required
The book being loaned. See Libro interface for details.
usuario
any
required
The user who requested the loan. This is the complete user object returned from the Spring Boot backend.

Estado Enum

The estado property uses a string literal union type with three possible values:
type EstadoPrestamo = 'PENDIENTE' | 'APROBADO' | 'RECHAZADO';

Estado Values

PENDIENTE
string
Initial state when a user requests a book loan. Awaiting administrator approval.
APROBADO
string
The loan has been approved by an administrator. The book is now marked as unavailable.
RECHAZADO
string
The loan request has been rejected by an administrator.

Usage Examples

Requesting a Loan (User)

import { PrestamoService } from './core/services/prestamo';

const libroId = 1;

this.prestamoService.solicitar(libroId).subscribe({
  next: (response) => {
    console.log('Loan requested:', response);
    // Response is typically a success message
  },
  error: (err) => {
    console.error('Loan request failed:', err);
  }
});

Viewing All Loans (Admin)

import { Prestamo } from './core/models/prestamo';

this.prestamoService.getAll().subscribe({
  next: (prestamos: Prestamo[]) => {
    prestamos.forEach(prestamo => {
      console.log(`Loan #${prestamo.id}:`);
      console.log(`  Book: ${prestamo.libro.titulo}`);
      console.log(`  Status: ${prestamo.estado}`);
      console.log(`  Requested: ${prestamo.fechaSolicitud}`);
      if (prestamo.fechaDevolucion) {
        console.log(`  Return date: ${prestamo.fechaDevolucion}`);
      }
    });
  },
  error: (err) => console.error('Error fetching loans:', err)
});

Viewing User’s Own Loans

this.prestamoService.getMisPrestamos().subscribe({
  next: (misPrestamos: Prestamo[]) => {
    const pendientes = misPrestamos.filter(p => p.estado === 'PENDIENTE');
    const aprobados = misPrestamos.filter(p => p.estado === 'APROBADO');
    const rechazados = misPrestamos.filter(p => p.estado === 'RECHAZADO');
    
    console.log(`Pending: ${pendientes.length}`);
    console.log(`Approved: ${aprobados.length}`);
    console.log(`Rejected: ${rechazados.length}`);
  }
});

Approving a Loan (Admin)

const prestamoId = 5;

this.prestamoService.aprobar(prestamoId).subscribe({
  next: (response) => {
    console.log('Loan approved:', response);
    // The book's disponible status will be updated to false
  },
  error: (err) => {
    console.error('Approval failed:', err);
  }
});

Rejecting a Loan (Admin)

const prestamoId = 6;

this.prestamoService.rechazar(prestamoId).subscribe({
  next: (response) => {
    console.log('Loan rejected:', response);
  },
  error: (err) => {
    console.error('Rejection failed:', err);
  }
});

Filtering Loans by Status

import { Prestamo } from './core/models/prestamo';

getPrestamosByEstado(estado: 'PENDIENTE' | 'APROBADO' | 'RECHAZADO') {
  this.prestamoService.getAll().subscribe({
    next: (prestamos: Prestamo[]) => {
      const filtered = prestamos.filter(p => p.estado === estado);
      console.log(`${filtered.length} loans with status ${estado}`);
      return filtered;
    }
  });
}

Checking Book Availability Before Requesting

import { Libro } from './core/models/libro';

solicitarPrestamo(libro: Libro) {
  if (!libro.disponible) {
    console.error('Book is not available for loan');
    return;
  }
  
  this.prestamoService.solicitar(libro.id).subscribe({
    next: (response) => {
      console.log('Loan requested successfully');
    },
    error: (err) => {
      console.error('Error:', err);
    }
  });
}

Template Usage

<!-- Admin: Loan management table -->
<table>
  <thead>
    <tr>
      <th>ID</th>
      <th>Book</th>
      <th>User</th>
      <th>Request Date</th>
      <th>Status</th>
      <th>Actions</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let prestamo of prestamos">
      <td>{{ prestamo.id }}</td>
      <td>{{ prestamo.libro.titulo }}</td>
      <td>{{ prestamo.usuario.username }}</td>
      <td>{{ prestamo.fechaSolicitud | date }}</td>
      <td>
        <span [class]="'badge-' + prestamo.estado.toLowerCase()">
          {{ prestamo.estado }}
        </span>
      </td>
      <td>
        <button 
          *ngIf="prestamo.estado === 'PENDIENTE'"
          (click)="aprobar(prestamo.id)">
          Aprobar
        </button>
        <button 
          *ngIf="prestamo.estado === 'PENDIENTE'"
          (click)="rechazar(prestamo.id)">
          Rechazar
        </button>
      </td>
    </tr>
  </tbody>
</table>

<!-- User: My loans list -->
<div *ngFor="let prestamo of misPrestamos" class="loan-card">
  <h3>{{ prestamo.libro.titulo }}</h3>
  <p>Requested: {{ prestamo.fechaSolicitud | date:'short' }}</p>
  <p *ngIf="prestamo.fechaDevolucion">
    Return by: {{ prestamo.fechaDevolucion | date:'short' }}
  </p>
  <span class="status" [ngClass]="{
    'pending': prestamo.estado === 'PENDIENTE',
    'approved': prestamo.estado === 'APROBADO',
    'rejected': prestamo.estado === 'RECHAZADO'
  }">
    {{ prestamo.estado }}
  </span>
</div>

Component Implementation Example

import { Component, OnInit } from '@angular/core';
import { PrestamoService } from './core/services/prestamo';
import { Prestamo } from './core/models/prestamo';

@Component({
  selector: 'app-prestamo-list',
  templateUrl: './prestamo-list.component.html'
})
export class PrestamoListComponent implements OnInit {
  prestamos: Prestamo[] = [];
  loading = false;

  constructor(private prestamoService: PrestamoService) {}

  ngOnInit() {
    this.loadPrestamos();
  }

  loadPrestamos() {
    this.loading = true;
    this.prestamoService.getAll().subscribe({
      next: (data) => {
        this.prestamos = data;
        this.loading = false;
      },
      error: (err) => {
        console.error('Error loading loans:', err);
        this.loading = false;
      }
    });
  }

  aprobar(id: number) {
    this.prestamoService.aprobar(id).subscribe({
      next: () => {
        console.log('Loan approved');
        this.loadPrestamos(); // Reload list
      },
      error: (err) => console.error('Error:', err)
    });
  }

  rechazar(id: number) {
    this.prestamoService.rechazar(id).subscribe({
      next: () => {
        console.log('Loan rejected');
        this.loadPrestamos(); // Reload list
      },
      error: (err) => console.error('Error:', err)
    });
  }

  getPendingCount(): number {
    return this.prestamos.filter(p => p.estado === 'PENDIENTE').length;
  }
}
  • Libro - Book interface referenced by Prestamo
  • Autor - Author interface (referenced through Libro)
  • Genero - Genre interface (referenced through Libro)

Business Rules

When a loan is approved (APROBADO), the associated book’s disponible property is automatically set to false by the backend.
Users can only request loans for books where libro.disponible === true. The backend will reject requests for unavailable books.
The fechaSolicitud is automatically set by the backend when the loan is created. You don’t need to provide it when requesting a loan.

Notes

Consider implementing date formatting utilities to display fechaSolicitud and fechaDevolucion in a user-friendly format.
The usuario field contains the complete user object from Spring Boot. The exact structure depends on your backend User model.

Build docs developers (and LLMs) love