PagoService.java
package com.licensis.notaire.service;
import com.licensis.notaire.negocio.Pago;
import com.licensis.notaire.negocio.Presupuesto;
import com.licensis.notaire.repository.PagoRepository;
import com.licensis.notaire.repository.PresupuestoRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.Optional;
@Service
public class PagoService {
private static final Logger log = LoggerFactory.getLogger(PagoService.class);
private final PagoRepository pagoRepository;
private final PresupuestoRepository presupuestoRepository;
public PagoService(PagoRepository pagoRepository, PresupuestoRepository presupuestoRepository) {
this.pagoRepository = pagoRepository;
this.presupuestoRepository = presupuestoRepository;
}
/**
* CU15 - Procesar pago: Registra un nuevo pago para un presupuesto.
* Calcula el saldo pendiente y valida que el monto no exceda el total.
*/
@Transactional
public Pago procesarPago(Integer idPresupuesto, Float monto, Date fecha, String observaciones) {
log.info("Procesando pago para presupuesto {}: monto={}", idPresupuesto, monto);
Presupuesto presupuesto = presupuestoRepository.findById(idPresupuesto)
.orElseThrow(() -> new IllegalArgumentException(
"Presupuesto no encontrado con ID: " + idPresupuesto));
if (monto == null || monto <= 0) {
throw new IllegalArgumentException("El monto del pago debe ser mayor a cero");
}
Float totalPresupuesto = calcularTotalPresupuesto(presupuesto);
Float totalPagado = pagoRepository.sumMontoByPresupuestoId(idPresupuesto);
Float saldoPendiente = totalPresupuesto - (totalPagado != null ? totalPagado : 0f);
log.info("Presupuesto total: {}, Pagado: {}, Saldo pendiente: {}",
totalPresupuesto, totalPagado, saldoPendiente);
Pago pago = new Pago();
pago.setMonto(monto);
pago.setFecha(fecha != null ? fecha : new Date());
pago.setObservaciones(observaciones);
pago.setPresupuesto(presupuesto);
Pago savedPago = pagoRepository.save(pago);
log.info("Pago registrado exitosamente: ID={}", savedPago.getIdPago());
return savedPago;
}
/**
* CU47 - Consultar Pago: Obtiene un pago por su ID.
*/
@Transactional(readOnly = true)
public Optional<Pago> consultarPago(Integer idPago) {
log.debug("Consultando pago con ID: {}", idPago);
return pagoRepository.findById(idPago);
}
/**
* Obtiene todos los pagos de un presupuesto.
*/
@Transactional(readOnly = true)
public List<Pago> findPagosByPresupuesto(Integer idPresupuesto) {
return pagoRepository.findByFkIdPresupuestoIdPresupuesto(idPresupuesto);
}
/**
* Calcula el saldo pendiente de un presupuesto.
*/
@Transactional(readOnly = true)
public Float calcularSaldoPendiente(Integer idPresupuesto) {
Presupuesto presupuesto = presupuestoRepository.findById(idPresupuesto)
.orElseThrow(() -> new IllegalArgumentException(
"Presupuesto no encontrado con ID: " + idPresupuesto));
Float totalPresupuesto = calcularTotalPresupuesto(presupuesto);
Float totalPagado = pagoRepository.sumMontoByPresupuestoId(idPresupuesto);
Float saldoPendiente = totalPresupuesto - (totalPagado != null ? totalPagado : 0f);
log.debug("Saldo pendiente para presupuesto {}: {}", idPresupuesto, saldoPendiente);
return saldoPendiente;
}
/**
* Calcula el total de un presupuesto sumando los items.
*/
private Float calcularTotalPresupuesto(Presupuesto presupuesto) {
if (presupuesto.getItemList() == null || presupuesto.getItemList().isEmpty()) {
return presupuesto.getMontoInmueble() != null ? presupuesto.getMontoInmueble() : 0f;
}
float total = 0f;
for (var item : presupuesto.getItemList()) {
total += item.getValor();
if (item.getPorcentaje() != null && item.getPorcentaje() > 0) {
total += total * (item.getPorcentaje() / 100.0f);
}
}
return total;
}
/**
* Obtiene todos los pagos.
*/
@Transactional(readOnly = true)
public List<Pago> findAll() {
return pagoRepository.findAll();
}
/**
* Obtiene pagos en un rango de fechas.
*/
@Transactional(readOnly = true)
public List<Pago> findPagosByFechaRange(Date startDate, Date endDate) {
return pagoRepository.findByFechaBetween(startDate, endDate);
}
/**
* Elimina un pago por su ID.
*/
@Transactional
public void deletePago(Integer idPago) {
log.info("Eliminando pago con ID: {}", idPago);
if (!pagoRepository.existsById(idPago)) {
throw new IllegalArgumentException("Pago no encontrado con ID: " + idPago);
}
pagoRepository.deleteById(idPago);
log.info("Pago eliminado exitosamente: ID={}", idPago);
}
/**
* Edita un pago existente.
*/
@Transactional
public Pago editarPago(Integer idPago, Float monto, Date fecha, String observaciones) {
log.info("Editando pago con ID: {}", idPago);
Pago pago = pagoRepository.findById(idPago)
.orElseThrow(() -> new IllegalArgumentException("Pago no encontrado con ID: " + idPago));
if (monto != null) {
if (monto <= 0) {
throw new IllegalArgumentException("El monto del pago debe ser mayor a cero");
}
pago.setMonto(monto);
}
if (fecha != null) {
pago.setFecha(fecha);
}
if (observaciones != null) {
pago.setObservaciones(observaciones);
}
Pago savedPago = pagoRepository.save(pago);
log.info("Pago editado exitosamente: ID={}", savedPago.getIdPago());
return savedPago;
}
}