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
Unique identifier for the loan. Auto-generated by the backend.
The date and time when the loan was requested. Typically in ISO 8601 format (e.g., "2024-03-15T10:30:00").
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
The book being loaned. See Libro interface for details.
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
Initial state when a user requests a book loan. Awaiting administrator approval.
The loan has been approved by an administrator. The book is now marked as unavailable.
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.