Este proyecto es una aplicación Java con Spring Boot y Maven para la gestión de facturación electrónica. Permite:
- Registrar clientes con identificación única y datos legales.
- Gestionar productos (ítems), incluyendo impuestos, descuentos y retenciones.
- Crear facturas asociando clientes e ítems, con soporte para códigos de referencia y métodos de pago.
- Utilizar Spring Data JPA para el acceso a datos y relaciones entre entidades (@ManyToMany y @ManyToOne).
- Manejar problemas comunes de Hibernate como la carga perezosa (LazyInitializationException).
- Interfaz de consola.
El proyecto aplica buenas prácticas de Java, Spring Boot y Hibernate en escenarios reales de facturación.
Principal
package com.diego.billing.principal;
public class Principal {
Scanner scan = new Scanner(System.in);
private BillingRepository billingRepository;
private CustomerRepository customerRepository;
private ItemRepository itemRepository;
public void muestraElMenu() {
var opcion = -1;
while (opcion != 0) {
var menu = """
2 - Ver clientes
4 - Ver items
5 - Crear factura
6 - Ver facturas
7 - Buscar factura por código de referencia
0 - Salir
""";
System.out.println(menu);
opcion = scan.nextInt();
switch (opcion) {
case 5:
crearFactura();
break;
case 6:
verFacturas();
break;
case 7:
verFacturaPorNombre();
break;
case 0:
System.out.println("Cerrando la aplicación...");
break;
default:
System.out.println("Opción inválida");
}
}
}
public void crearFactura() {
Billing billing = new Billing();
billing.setItems(new ArrayList<>());
System.out.print("Document: ");
billing.setDocument(scan.nextLine());
System.out.print("Numbering Range ID: ");
billing.setNumberingRangeId(scan.nextInt());
scan.nextLine(); // Limpiar buffer
System.out.print("Reference Code: ");
String referenceCode = scan.nextLine();
billing.setReferenceCode(referenceCode);
System.out.print("Observation: ");
billing.setObservation(scan.nextLine());
System.out.print("Payment Method Code: ");
billing.setPaymentMethodCode(scan.nextInt());
scan.nextLine(); // Clear buffer
// Select or create customer
System.out.print("Enter customer ID (or 0 to create new): ");
Long customerId = scan.nextLong();
scan.nextLine();
Customer customer;
if (customerId == 0) {
customer = crearCliente();
} else {
customer = customerRepository.findById(customerId).orElseGet(this::crearCliente);
}
billing.setCustomer(customer);
String addMore;
do {
Item item;
System.out.print("Enter item ID (or 0 to create new): ");
Long itemId = scan.nextLong();
scan.nextLine();
if (itemId == 0) {
item = crearItem();
} else {
item = itemRepository.findById(itemId).orElseThrow();
}
billing.getItems().add(item);
System.out.print("Add another item? (y/n): ");
addMore = scan.nextLine();
} while (addMore.equalsIgnoreCase("y"));
// Save billing (cascade saves items)
billingRepository.save(billing);
System.out.println("✅ Invoice created successfully:\n" + billing);
}
private void verFacturas(){
List<Billing> facturas = billingRepository.findAll();
if (facturas.isEmpty()) {
System.out.println("No hay facturas registradas.");
} else {
facturas.forEach(System.out::println);
}
}
}
Services:
package com.diego.billing.service;
@Service
public class BillingService {
private final BillingRepository repository;
public BillingService(BillingRepository repository) {
this.repository = repository;
}
public Billing save(Billing billing) {
return repository.save(billing);
}
public List<Billing> findAll() {
return repository.findAll();
}
public List<Billing> findByReferenceCode(String referenceCode) {
return repository.findAll()
.stream()
.filter(b -> b.getReferenceCode().equalsIgnoreCase(referenceCode))
.toList();
}
}