package de.rwth.idsg.bikeman.service; import de.rwth.idsg.bikeman.domain.Booking; import de.rwth.idsg.bikeman.domain.CardAccount; import de.rwth.idsg.bikeman.domain.Pedelec; import de.rwth.idsg.bikeman.domain.Reservation; import de.rwth.idsg.bikeman.domain.StationSlot; import de.rwth.idsg.bikeman.domain.Transaction; import de.rwth.idsg.bikeman.ixsi.service.BookingService; import de.rwth.idsg.bikeman.psinterface.dto.request.CancelReservationDTO; import de.rwth.idsg.bikeman.psinterface.dto.request.ReserveNowDTO; import de.rwth.idsg.bikeman.psinterface.dto.request.StartTransactionDTO; import de.rwth.idsg.bikeman.psinterface.exception.PsException; import de.rwth.idsg.bikeman.psinterface.repository.PsiTransactionRepository; import de.rwth.idsg.bikeman.psinterface.rest.PsiService; import de.rwth.idsg.bikeman.psinterface.rest.client.StationClient; import de.rwth.idsg.bikeman.repository.BookingRepository; import de.rwth.idsg.bikeman.repository.ReservationRepository; import de.rwth.idsg.bikeman.repository.StationRepository; import de.rwth.idsg.bikeman.repository.StationSlotRepository; import de.rwth.idsg.bikeman.security.SecurityUtils; import de.rwth.idsg.bikeman.web.rest.dto.modify.ChangeStationOperationStateDTO; import de.rwth.idsg.bikeman.web.rest.dto.modify.CreateEditStationDTO; import de.rwth.idsg.bikeman.web.rest.dto.modify.StationConfigurationDTO; import de.rwth.idsg.bikeman.web.rest.dto.view.ViewErrorDTO; import de.rwth.idsg.bikeman.web.rest.dto.view.ViewStationDTO; import de.rwth.idsg.bikeman.web.rest.exception.DatabaseException; import de.rwth.idsg.bikeman.web.rest.exception.ErrorMessage; import lombok.extern.slf4j.Slf4j; import org.joda.time.DateTime; import org.joda.time.LocalDateTime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; /** * Created by max on 18/08/14. */ @Service @Slf4j public class StationService { @Autowired private StationClient stationClient; @Autowired private StationRepository stationRepository; @Autowired private OperationStateService operationStateService; @Autowired private StationSlotRepository stationSlotRepository; @Autowired private TransactionEventService transactionEventService; @Autowired private PsiService psiService; @Autowired private PsiTransactionRepository transactionRepository; @Autowired private BookingService bookingService; @Autowired private BookingRepository bookingRepository; @Autowired private ReservationRepository reservationRepository; @Autowired private CardAccountService cardAccountService; public void create(CreateEditStationDTO dto) throws DatabaseException { stationRepository.create(dto); } public List<ViewStationDTO> getAll() throws DatabaseException { return stationRepository.findAll(); } public ViewStationDTO get(Long id) throws DatabaseException { return stationRepository.findOne(id); } public void reboot(Long id) throws DatabaseException { String endpointAddress = stationRepository.getEndpointAddress(id); stationClient.reboot(endpointAddress); } public StationConfigurationDTO getConfig(Long id) throws DatabaseException { String endpointAddress = stationRepository.getEndpointAddress(id); return stationClient.getConfig(endpointAddress); } public List<ViewErrorDTO> getErrors() throws DatabaseException { List<ViewErrorDTO> stationErrors = stationRepository.findErrors(); List<ViewErrorDTO> stationSlotErrors = stationSlotRepository.findErrors(); List<ViewErrorDTO> errors = new ArrayList<>(stationErrors); errors.addAll(stationSlotErrors); return errors .stream() .sorted((e1, e2) -> e2.getLastUpdated().compareTo(e1.getLastUpdated())) .collect(Collectors.toList()); } public void updateConfig(Long id, StationConfigurationDTO dto) throws DatabaseException { // TODO: cmsURI != endpointAddress. cmsURI refers from station to cms. String endpointAddress = stationRepository.getEndpointAddress(id); // String inputEndpointAddress = dto.getCmsURI(); // // if (!endpointAddress.equals(inputEndpointAddress)) { // stationRepository.updateEndpointAddress(id, inputEndpointAddress); // endpointAddress = inputEndpointAddress; // } stationClient.changeConfig(endpointAddress, dto); } public void updateStation(CreateEditStationDTO dto) throws DatabaseException { ChangeStationOperationStateDTO changeDTO = new ChangeStationOperationStateDTO(); changeDTO.setState(dto.getState()); // first, communicate with the station to update status // then, update in DB String endpointAddress = stationRepository.getEndpointAddress(dto.getStationId()); stationClient.changeOperationState(endpointAddress, changeDTO); stationRepository.update(dto); operationStateService.pushStationChange(dto); } public void changeSlotState(Long stationId, ChangeStationOperationStateDTO dto) throws DatabaseException { ChangeStationOperationStateDTO changeDTO = new ChangeStationOperationStateDTO(); changeDTO.setState(dto.getState()); changeDTO.setSlotPosition(dto.getSlotPosition()); // first, communicate with the station to update status // then, update in DB String endpointAddress = stationRepository.getEndpointAddress(stationId); stationClient.changeOperationState(endpointAddress, changeDTO); stationRepository.changeSlotState(stationId, dto.getSlotPosition(), dto.getState()); StationSlot stationSlot = stationSlotRepository.findByStationSlotPositionAndStationStationId(dto.getSlotPosition(), stationId); operationStateService.pushSlotChange(stationSlot); } @Async public void reserveNow(String endpointAddress, ReserveNowDTO reserveNowDTO) throws DatabaseException { stationClient.reserveNow(reserveNowDTO, endpointAddress); } @Async public void cancelReservation(String endpointAddress, CancelReservationDTO cancelReservationDTO) throws DatabaseException { stationClient.cancelReservation(cancelReservationDTO, endpointAddress); } @Transactional public void unlockSlot(Long stationId, Long stationSlotId) { String endpointAddress = stationRepository.getEndpointAddress(stationId); StationSlot slot = stationSlotRepository.findOne(stationSlotId); List<CardAccount> cardAccounts = cardAccountService.getCardAccountsOfCurrentUser(); String cardId = ""; Pedelec pedelec = slot.getPedelec(); if (cardAccounts.isEmpty()) { if (pedelec != null) { log.error("Maintainer (id:{}) has no proper CardAccount for unlocking slot (id:{}) with pedelec (id:{})", SecurityUtils.getCurrentLogin(), stationSlotId, pedelec.getPedelecId()); throw new DatabaseException("No valid card account found."); } } else { cardId = cardAccounts.get(0).getCardId(); } // send unlock command to station try { stationClient.unlockSlot(slot.getStationSlotPosition(), endpointAddress); } catch (PsException e) { log.error("Error occured while opening StationSlot with ID: {}", stationSlotId); } // Without pedelec it is not necessary to start a maintenance transaction if (pedelec == null) { return; } // check for reservation for this pedelec and cancel reservations List<Reservation> reservations = reservationRepository .findByTimeFrameForPedelec(pedelec.getPedelecId(), LocalDateTime.now(), LocalDateTime.now().plusHours(1)); reservations.forEach(reservation -> bookingService.cancel(reservation.getBooking().getIxsiBookingId(), reservation.getCardAccount().getCardId()) ); // when pedelec is at specific slot, put pedelec in "maintenance" transaction StartTransactionDTO startTransactionDTO = StartTransactionDTO.builder() .timestamp(DateTime.now()) .pedelecManufacturerId(pedelec.getManufacturerId()) .slotManufacturerId(slot.getManufacturerId()) .stationManufacturerId(slot.getStation().getManufacturerId()) .cardId(cardId) .build(); transactionEventService.createAndSaveStartTransactionEvent(startTransactionDTO); Transaction transaction = transactionRepository.start(startTransactionDTO); Booking booking = new Booking(); booking.setTransaction(transaction); bookingRepository.save(booking); psiService.performStartPush(startTransactionDTO); } }