package com.tourMate.dao.impl; import com.tourMate.dao.HotelDao; import com.tourMate.entities.*; import com.tourMate.events.OnHotelReservationEvent; import com.tourMate.events.OnRegistrationSuccessEvent; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import jakarta.transaction.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import java.util.Calendar; import java.util.Date; import java.util.List; @Service public class HotelDaoImpl implements HotelDao { @PersistenceContext EntityManager em; @Autowired ApplicationEventPublisher eventPublisher; @Override @Transactional public void createHotel(Hotels hotel) { em.persist(hotel); } @Override public List getHotels() { return em.createQuery("select h from Hotels h order by h.hotelId").getResultList(); } @Override public List getHotelsForUser(User u) { return em.createQuery("select h from Hotels h where h.owner = :u or h.owner in :users") .setParameter("u", u) .setParameter("users", u.getConnectedAccounts()) .getResultList(); } @Transactional @Override public void editHotel(Hotels hotel) { em.persist(hotel); } @Transactional @Override public void deleteHotel(Hotels hotel) { em.remove(hotel); } @Override public Hotels findHotelByID(long hotelId) { return em.find(Hotels.class, hotelId); } @Override public List getHotelImages(Hotels hotel) { return em.createQuery("select hi from HotelsImages hi where hi.hotel = :hotel").setParameter("hotel", hotel).getResultList(); } @Override @Transactional public void addHotelImage(HotelsImages image) { em.persist(image); } @Transactional @Override public void addRoomImage(HotelRoomImages x) { em.persist(x); } @Override @Transactional public void saveReservation(HotelRoomReservations hotelRoomReservations) { em.persist(hotelRoomReservations); } @Override @Transactional public HotelsImages findHotelImageById(long hotelImageId) { return em.find(HotelsImages.class, hotelImageId); } @Override @Transactional public void deleteHotelImage(HotelsImages hotelsImages) { em.remove(hotelsImages); } @Override public List getRoomsOfHotel(Hotels hotel) { return em.createQuery("SELECT hr from HotelRoom hr where hr.hotel = :hotel").setParameter("hotel", hotel).getResultList(); } @Override public List getRoomsAvailable(Long id) { return em.createQuery("SELECT hra from HotelRoomAvailable hra WHERE hra.hotelRoom.id = :hotelRoomId").setParameter("hotelRoomId", id).getResultList(); } @Override public HotelRoom findRoomById(long hotelRoomId) { return em.find(HotelRoom.class, hotelRoomId); } @Override public List getRoomImages(HotelRoom hotelRoom) { return em.createQuery("select i from HotelRoomImages i where i.room = :hotelRoom").setParameter("hotelRoom", hotelRoom).getResultList(); } @Transactional @Override public void createRoom(HotelRoom hotelRoom) { em.persist(hotelRoom); } @Transactional @Override public void editRoom(HotelRoom hr) { em.persist(hr); } @Transactional @Override public void deleteRoom(HotelRoom hr) { em.remove(hr); } @Transactional @Override public void createRoomAvailible(HotelRoomAvailable hra) { em.persist(hra); } @Transactional @Override public void editRoomAvailible(HotelRoomAvailable hr) { em.persist(hr); } @Transactional @Override public void deleteRoomAvailible(HotelRoomAvailable hra) { em.remove(hra); } @Override public HotelRoomAvailable findAvailibleRoomById(long hotelRoomAvailableId) { return em.find(HotelRoomAvailable.class, hotelRoomAvailableId); } @Override public List getRoomsAvailibility() { return em.createQuery("select hra from HotelRoomAvailable hra").getResultList(); } @Override public List getRoomsAvailibilityByHotel(Hotels hotel) { return em.createQuery("select hr from HotelRoomAvailable hr where hr.hotelRoom.hotel = :hotel").setParameter("hotel", hotel).getResultList(); } @Override public List getRoomsAvailibilityByDateAndLocation(String hotelLocation, Date dateFrom, Date dateTo, int numberOfBeds, Boolean flexible) { if(flexible) { Calendar calendar = Calendar.getInstance(); Calendar calendar1 = Calendar.getInstance(); calendar.setTime(dateTo); calendar1.setTime(dateFrom); return em.createQuery("SELECT hr FROM HotelRoomAvailable hr WHERE " + "((hr.dateFrom <= :dateTo AND hr.dateTo >= :dateFrom) OR " + "(hr.dateFrom <= :dateToMinus1 AND hr.dateTo >= :dateFromMinus1) OR " + "(hr.dateFrom <= :dateToMinus2 AND hr.dateTo >= :dateFromMinus2) OR " + "(hr.dateFrom <= :dateToMinus3 AND hr.dateTo >= :dateFromMinus3) OR " + "(hr.dateFrom <= :dateToPlus1 AND hr.dateTo >= :dateFromPlus1) OR " + "(hr.dateFrom <= :dateToPlus2 AND hr.dateTo >= :dateFromPlus2) OR " + "(hr.dateFrom <= :dateToPlus3 AND hr.dateTo >= :dateFromPlus3)) " + "AND hr.hotelRoom.hotel.hotelLocation LIKE :hotelLocation " + "AND hr.hotelRoom.numOfBeds >= :numBeds") .setParameter("hotelLocation", hotelLocation) .setParameter("dateFrom", dateFrom) .setParameter("dateTo", dateTo) .setParameter("dateToMinus1", subtractDays(calendar, 1)) .setParameter("dateToMinus2", subtractDays(calendar, 2)) .setParameter("dateToMinus3", subtractDays(calendar, 3)) .setParameter("dateToPlus1", addDays(calendar, 1)) .setParameter("dateToPlus2", addDays(calendar, 2)) .setParameter("dateToPlus3", addDays(calendar, 3)) .setParameter("dateFromMinus1", subtractDays(calendar1, 1)) .setParameter("dateFromMinus2", subtractDays(calendar1, 2)) .setParameter("dateFromMinus3", subtractDays(calendar1, 3)) .setParameter("dateFromPlus1", addDays(calendar1, 1)) .setParameter("dateFromPlus2", addDays(calendar1, 2)) .setParameter("dateFromPlus3", addDays(calendar1, 3)) .setParameter("numBeds", numberOfBeds) .getResultList(); } else { return em.createQuery("SELECT hr FROM HotelRoomAvailable hr WHERE " + "((hr.dateFrom <= :dateTo AND hr.dateTo >= :dateFrom)) " + "AND hr.hotelRoom.hotel.hotelLocation LIKE :hotelLocation " + "AND hr.hotelRoom.numOfBeds >= :numBeds") .setParameter("hotelLocation", hotelLocation) .setParameter("dateFrom", dateFrom) .setParameter("dateTo", dateTo) .setParameter("numBeds", numberOfBeds) .getResultList(); } } private Date addDays(Calendar calendar, int days) { Calendar newCalendar = (Calendar) calendar.clone(); newCalendar.add(Calendar.DAY_OF_MONTH, days); return newCalendar.getTime(); } private Date subtractDays(Calendar calendar, int days) { Calendar newCalendar = (Calendar) calendar.clone(); newCalendar.add(Calendar.DAY_OF_MONTH, -days); return newCalendar.getTime(); } @Override @Transactional public void createReservation(HotelRoomReservations r) { em.persist(r); eventPublisher.publishEvent(new OnHotelReservationEvent(r.getUser(), r)); } @Override @Transactional public void editReservation(HotelRoomReservations hr) { em.persist(hr); } @Transactional @Override public void deleteReservation(HotelRoomReservations hr) { em.remove(hr); } @Override public HotelRoomReservations findReservationById(long hotelRoomReservedId) { return em.find(HotelRoomReservations.class, hotelRoomReservedId); } @Override public List findReservationByUser(User user) { return em.createQuery("select hr from HotelRoomReservations hr where hr.user = :user and hr.dateTo >= now()") .setParameter("user", user).getResultList(); } @Override public List findReservationByHotel(Hotels hotel) { List hotelRooms = getRoomsOfHotel(hotel); return em.createQuery("select hr from HotelRoomReservations hr where hr.hotelRoom.hotel = :hotel").setParameter("hotel", hotel).getResultList(); } @Override public List getReservations() { return em.createQuery("select hr from HotelRoomReservations hr order by hr.user.name").getResultList(); } @Override public List findReviewsByHotel(Hotels hotel) { return em.createQuery("select r from Reviews r where r.hotel = :hotel") .setParameter("hotel", hotel) .getResultList(); } @Override public List findPastReservationByUser(User u) { return em.createQuery("select hr from HotelRoomReservations hr where hr.user = :user and hr.dateTo <= now()") .setParameter("user", u).getResultList(); } @Override public List getReservationsInPeriod(String hotelLocation, Date dateFrom, Date dateTo) { return em.createQuery("select hr from HotelRoomReservations hr where hr.hotelRoom.hotel.hotelLocation like :hotelLocation and (hr.dateFrom between :dateFrom and :dateTo) or (hr.dateTo between :dateFrom and :dateTo)") .setParameter("hotelLocation", hotelLocation) .setParameter("dateFrom", dateFrom) .setParameter("dateTo", dateTo) .getResultList(); } @Override public List getHotelsByLocation(String hotelLocation) { return em.createQuery("select h from Hotels h where h.hotelLocation like :hotelLocation") .setParameter("hotelLocation", hotelLocation) .getResultList(); } }