diff --git a/src/main/java/com/example/fercoganbackend/controller/HistorialLotesController.java b/src/main/java/com/example/fercoganbackend/controller/HistorialLotesController.java new file mode 100644 index 0000000..dad4322 --- /dev/null +++ b/src/main/java/com/example/fercoganbackend/controller/HistorialLotesController.java @@ -0,0 +1,31 @@ +package com.example.fercoganbackend.controller; + +import com.example.fercoganbackend.dto.PujaRequest; +import com.example.fercoganbackend.dto.PujaResponse; +import com.example.fercoganbackend.entity.HistorialLotes; +import com.example.fercoganbackend.service.HistorialLotesService; + +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/api/HistorialPujas") +public class HistorialLotesController { + + private final HistorialLotesService historialLote; + + public HistorialLotesController(HistorialLotesService historialLote) { + this.historialLote = historialLote; + } + + @PostMapping + public PujaResponse realizarPuja(@RequestBody PujaRequest request) { + return historialLote.registrarPuja(request); + } + + @GetMapping + public List getHistorialLote(){ + return historialLote.getHistorialLoteAll(); + } +} diff --git a/src/main/java/com/example/fercoganbackend/controller/PujaController.java b/src/main/java/com/example/fercoganbackend/controller/PujaController.java index 3b6eaa6..4e5dbc3 100644 --- a/src/main/java/com/example/fercoganbackend/controller/PujaController.java +++ b/src/main/java/com/example/fercoganbackend/controller/PujaController.java @@ -20,16 +20,31 @@ public class PujaController { return pujaService.findAll(); } - @GetMapping("/{id}") + @GetMapping("/id/{id}") public ResponseEntity getById(@PathVariable Long id) { return pujaService.findById(id) .map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); } + + @GetMapping("/informe/{remateId}") + public List getForInforme(@PathVariable Long remateId){ + return pujaService.fingForReporte(remateId); + } + @GetMapping("/remate/{id}") + public List getForRemate(@PathVariable Long id){ + return pujaService.findForRemtae(id); + } + + //get coincidir con lote y remate + @GetMapping("/loteyremate/{loteId}/{remateId}") + public List getForLoteAndRemate(@PathVariable Long loteId,@PathVariable Long remateId){ + return pujaService.findForLoteAndRemate(loteId,remateId); + } @PostMapping - public Puja create(@RequestBody Puja remate) { - return pujaService.save(remate); + public Puja create(@RequestBody Puja puja) { + return pujaService.save(puja); } @PutMapping("/{id}") diff --git a/src/main/java/com/example/fercoganbackend/dto/PujaRequest.java b/src/main/java/com/example/fercoganbackend/dto/PujaRequest.java new file mode 100644 index 0000000..5835b86 --- /dev/null +++ b/src/main/java/com/example/fercoganbackend/dto/PujaRequest.java @@ -0,0 +1,29 @@ +package com.example.fercoganbackend.dto; + +import java.time.LocalDateTime; + +public class PujaRequest { + private LocalDateTime fecha; + private Double monto; + private Boolean visible; + + private Long usuarioId; + private Long cabanaId; + private Long loteId; + private Long remateId; + + public Long getRemateId(){ + return remateId; + } + public Long getUsuarioId() { + return usuarioId; + } + + public Long getLoteId() { + return loteId; + } + + public Double getMonto() { + return monto; + } +} diff --git a/src/main/java/com/example/fercoganbackend/dto/PujaResponse.java b/src/main/java/com/example/fercoganbackend/dto/PujaResponse.java new file mode 100644 index 0000000..e8b682d --- /dev/null +++ b/src/main/java/com/example/fercoganbackend/dto/PujaResponse.java @@ -0,0 +1,53 @@ +package com.example.fercoganbackend.dto; + +import java.time.LocalDateTime; + +public class PujaResponse { + + private Long pujaId; + private Long loteId; + private Long remateId; + private Long usuarioId; + + private Double montoPujado; + private LocalDateTime fecha; + private String estado; + + public PujaResponse(Long pujaId, Long loteId, Long usuarioId,Long remateId, + Double montoPujado, LocalDateTime fecha, String estado) { + this.pujaId = pujaId; + this.loteId = loteId; + this.remateId = remateId; + this.usuarioId = usuarioId; + this.montoPujado = montoPujado; + this.fecha = fecha; + this.estado = estado; + } + public Long getRemateId(){ + return remateId; + } + + public Long getPujaId() { + return pujaId; + } + + public Long getLoteId() { + return loteId; + } + + public Long getUsuarioId() { + return usuarioId; + } + + public Double getMontoPujado() { + return montoPujado; + } + + public LocalDateTime getFecha() { + return fecha; + } + + public String getEstado() { + return estado; + } +} diff --git a/src/main/java/com/example/fercoganbackend/entity/HistorialLotes.java b/src/main/java/com/example/fercoganbackend/entity/HistorialLotes.java new file mode 100644 index 0000000..28228d1 --- /dev/null +++ b/src/main/java/com/example/fercoganbackend/entity/HistorialLotes.java @@ -0,0 +1,107 @@ +package com.example.fercoganbackend.entity; + + +import jakarta.persistence.*; + +import java.time.LocalDateTime; + +@Entity +@Table(name = "historial_lotes") +public class HistorialLotes { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + // Usuario que realizó la puja + @ManyToOne + @JoinColumn(name = "usuario_id", nullable = false) + private Usuario usuario; + + // Lote al que pertenece la puja + @ManyToOne + @JoinColumn(name = "lote_id", nullable = false) + private Lote lote; + + @ManyToOne + @JoinColumn(name= "remate_id",nullable = false) + private Remate remate; + + // Monto pujado + @Column(nullable = false) + private Double monto; + + // Fecha y hora de la puja + @Column(nullable = false) + private LocalDateTime fecha; + + // Estado de la puja (opcional) + private String estado; + + public HistorialLotes() {} + + public HistorialLotes(Usuario usuario, Lote lote, Double monto, LocalDateTime fecha, String estado, Remate remate) { + this.usuario = usuario; + this.lote = lote; + this.remate = remate; + this.monto = monto; + this.fecha = fecha; + this.estado = estado; + } + + public Remate getRemate() { + return remate; + } + + public void setRemate(Remate remate) { + this.remate = remate; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Usuario getUsuario() { + return usuario; + } + + public void setUsuario(Usuario usuario) { + this.usuario = usuario; + } + + public Lote getLote() { + return lote; + } + + public void setLote(Lote lote) { + this.lote = lote; + } + + public Double getMonto() { + return monto; + } + + public void setMonto(Double monto) { + this.monto = monto; + } + + public LocalDateTime getFecha() { + return fecha; + } + + public void setFecha(LocalDateTime fecha) { + this.fecha = fecha; + } + + public String getEstado() { + return estado; + } + + public void setEstado(String estado) { + this.estado = estado; + } +} diff --git a/src/main/java/com/example/fercoganbackend/entity/Puja.java b/src/main/java/com/example/fercoganbackend/entity/Puja.java index d6291ee..742b492 100644 --- a/src/main/java/com/example/fercoganbackend/entity/Puja.java +++ b/src/main/java/com/example/fercoganbackend/entity/Puja.java @@ -28,6 +28,7 @@ public class Puja { @JoinColumn(name = "lote_id") private Lote lote; + public Long getId() { return id; } diff --git a/src/main/java/com/example/fercoganbackend/repository/HistorialLotesRepository.java b/src/main/java/com/example/fercoganbackend/repository/HistorialLotesRepository.java new file mode 100644 index 0000000..b0a3b38 --- /dev/null +++ b/src/main/java/com/example/fercoganbackend/repository/HistorialLotesRepository.java @@ -0,0 +1,30 @@ +package com.example.fercoganbackend.repository; + +import com.example.fercoganbackend.entity.HistorialLotes; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.time.LocalDateTime; +import java.util.List; + +@Repository +public interface HistorialLotesRepository extends JpaRepository { + + List findByLoteIdOrderByFechaDesc(Long loteId); + + HistorialLotes findFirstByLoteIdOrderByFechaDesc(Long loteId); + + List findByLote_Remate_Id(Long remateId); + + List findByLote_IdAndLote_Remate_Id(Long loteId, Long remateId); + + List findByLote_IdAndLote_Remate_IdAndFechaAfter( + Long loteId, + Long remateId, + LocalDateTime fecha + ); + List findByLote_Remate_IdAndFechaAfter( + Long remateId, + LocalDateTime fecha + ); +} diff --git a/src/main/java/com/example/fercoganbackend/repository/LoteRepository.java b/src/main/java/com/example/fercoganbackend/repository/LoteRepository.java index 214c3e6..01309d2 100644 --- a/src/main/java/com/example/fercoganbackend/repository/LoteRepository.java +++ b/src/main/java/com/example/fercoganbackend/repository/LoteRepository.java @@ -12,4 +12,5 @@ public interface LoteRepository extends JpaRepository { // Para paginación List findByCabanaId(Long cabanaId); + } diff --git a/src/main/java/com/example/fercoganbackend/repository/PujaRepository.java b/src/main/java/com/example/fercoganbackend/repository/PujaRepository.java index d2f18a6..32ec82f 100644 --- a/src/main/java/com/example/fercoganbackend/repository/PujaRepository.java +++ b/src/main/java/com/example/fercoganbackend/repository/PujaRepository.java @@ -1,6 +1,35 @@ package com.example.fercoganbackend.repository; +import com.example.fercoganbackend.entity.HistorialLotes; import com.example.fercoganbackend.entity.Puja; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; -public interface PujaRepository extends JpaRepository {} +import java.time.LocalDateTime; +import java.util.List; + +public interface PujaRepository extends JpaRepository { + + List findByLote_Remate_Id(Long remateId); + + List findByLote_IdAndLote_Remate_Id(Long loteId, Long remateId); + + List findByLote_IdAndLote_Remate_IdAndFechaAfter( + Long loteId, + Long remateId, + LocalDateTime fecha + ); + List findByLote_Remate_IdAndFechaAfter(Long id,LocalDateTime fecha); + + @Query(value = """ + SELECT p.* FROM pujas p + INNER JOIN ( + SELECT lote_id, MAX(monto) AS max_monto + FROM pujas + WHERE lote_id IN (SELECT id FROM lotes WHERE remate_id = :remateId) + GROUP BY lote_id + ) pm ON p.lote_id = pm.lote_id AND p.monto = pm.max_monto + """, nativeQuery = true) + List findMayorPujaPorLotePorRemateNative(Long remateId); + +} diff --git a/src/main/java/com/example/fercoganbackend/service/HistorialLotesService.java b/src/main/java/com/example/fercoganbackend/service/HistorialLotesService.java new file mode 100644 index 0000000..42a3e1b --- /dev/null +++ b/src/main/java/com/example/fercoganbackend/service/HistorialLotesService.java @@ -0,0 +1,72 @@ +package com.example.fercoganbackend.service; + +import com.example.fercoganbackend.dto.PujaRequest; +import com.example.fercoganbackend.dto.PujaResponse; +import com.example.fercoganbackend.entity.HistorialLotes; +import com.example.fercoganbackend.entity.Remate; +import com.example.fercoganbackend.entity.Usuario; +import com.example.fercoganbackend.entity.Lote; +import com.example.fercoganbackend.repository.HistorialLotesRepository; +import com.example.fercoganbackend.repository.RemateRepository; +import com.example.fercoganbackend.repository.UsuarioRepository; +import com.example.fercoganbackend.repository.LoteRepository; + +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +@Service +public class HistorialLotesService { + + private final HistorialLotesRepository historialRepo; + private final UsuarioRepository usuarioRepo; + private final LoteRepository loteRepo; + private final RemateRepository remateRepo; + + public HistorialLotesService(HistorialLotesRepository historialRepo, + UsuarioRepository usuarioRepo, + LoteRepository loteRepo, RemateRepository remateRepo) { + this.historialRepo = historialRepo; + this.remateRepo = remateRepo; + this.usuarioRepo = usuarioRepo; + this.loteRepo = loteRepo; + } + + public List getHistorialLoteAll(){ + return historialRepo.findAll(); + } + + public PujaResponse registrarPuja(PujaRequest request) { + + Usuario usuario = usuarioRepo.findById(request.getUsuarioId()) + .orElseThrow(() -> new RuntimeException("Usuario no encontrado")); + + Lote lote = loteRepo.findById(request.getLoteId()) + .orElseThrow(() -> new RuntimeException("Lote no encontrado")); + + Remate remate = remateRepo.findById(request.getRemateId()) + .orElseThrow(() -> new RuntimeException("No se encontro el remate")); + + HistorialLotes nuevaPuja = new HistorialLotes( + usuario, + lote, + request.getMonto(), + LocalDateTime.now(), + "ACEPTADA", + remate + ); + + historialRepo.save(nuevaPuja); + + return new PujaResponse( + nuevaPuja.getId(), + lote.getId(), + usuario.getId(), + remate.getId(), + nuevaPuja.getMonto(), + nuevaPuja.getFecha(), + nuevaPuja.getEstado() + ); + } +} diff --git a/src/main/java/com/example/fercoganbackend/service/PujaService.java b/src/main/java/com/example/fercoganbackend/service/PujaService.java index 7bf70bf..be1615f 100644 --- a/src/main/java/com/example/fercoganbackend/service/PujaService.java +++ b/src/main/java/com/example/fercoganbackend/service/PujaService.java @@ -1,15 +1,33 @@ package com.example.fercoganbackend.service; import com.example.fercoganbackend.entity.Puja; +import com.example.fercoganbackend.entity.Remate; import com.example.fercoganbackend.repository.PujaRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import com.example.fercoganbackend.repository.UsuarioRepository; +import com.example.fercoganbackend.repository.CabanaRepository; +import com.example.fercoganbackend.repository.LoteRepository; +import com.example.fercoganbackend.repository.RemateRepository; + +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @Service public class PujaService { + @Autowired + private UsuarioRepository usuarioRepository; + + @Autowired + private CabanaRepository cabanaRepository; + + @Autowired + private LoteRepository loteRepository; + + @Autowired + private RemateRepository remateRepository; @Autowired private PujaRepository pujaRepository; @@ -18,14 +36,57 @@ public class PujaService { return pujaRepository.findAll(); } + public List findForRemtae(Long id){ + return pujaRepository.findByLote_Remate_Id(id); + } + + public List findForLoteAndRemate(Long loteId, Long remateId){ + return pujaRepository.findByLote_IdAndLote_Remate_Id(loteId,remateId); + } + + public List findForLoteAndRemateAndDate(Long loteId, Long remateId, LocalDateTime fecha){ + return pujaRepository.findByLote_IdAndLote_Remate_IdAndFechaAfter(loteId, remateId, fecha); + } + public List fingForReporte(Long id){ + return pujaRepository.findMayorPujaPorLotePorRemateNative(id); + } public Optional findById(Long id) { return pujaRepository.findById(id); } - public Puja save(Puja remate) { - return pujaRepository.save(remate); + public Puja save(Puja puja) { + + // Validar USUARIO + if (puja.getUsuario() == null || puja.getUsuario().getId() == null) { + throw new RuntimeException("El usuario es obligatorio"); + } + var usuario = usuarioRepository.findById(puja.getUsuario().getId()) + .orElseThrow(() -> new RuntimeException("Usuario no encontrado")); + + // Validar CABAÑA + if (puja.getCabana() == null || puja.getCabana().getId() == null) { + throw new RuntimeException("La cabaña es obligatoria"); + } + var cabana = cabanaRepository.findById(puja.getCabana().getId()) + .orElseThrow(() -> new RuntimeException("Cabaña no encontrada")); + + // Validar LOTE + if (puja.getLote() == null || puja.getLote().getId() == null) { + throw new RuntimeException("El lote es obligatorio"); + } + var lote = loteRepository.findById(puja.getLote().getId()) + .orElseThrow(() -> new RuntimeException("Lote no encontrado")); + + + // Asignar entidades reales para que JPA las maneje correctamente + puja.setUsuario(usuario); + puja.setCabana(cabana); + puja.setLote(lote); + + return pujaRepository.save(puja); } + public void delete(Long id) { pujaRepository.deleteById(id); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 03fcd84..1b1d6d5 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,5 +1,5 @@ spring.application.name=fercoganbackend -spring.profiles.active=prod +spring.profiles.active=dev spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto=update