Changes between Version 4 and Version 5 of UseCaseImplementationsFinal


Ignore:
Timestamp:
02/04/24 18:25:32 (4 months ago)
Author:
211012
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • UseCaseImplementationsFinal

    v4 v5  
    297297}
    298298}}}
     299
     300=== Испраќа известување до корисници на услуги
     301За имплементација на оваа функционалност го користиме сервисот за испраќање пораки наведен погоре и дополнително имплементиран Listener и Event. Spring претставува event-driven архитектура, односно им овозможува на компононетите да комуницираат преку пропагација на настани во улога на publisher и subscriber. Овој механизам е типичен пример за примена на шаблонот Observer. И покарј тоа што голем дел од предефинираните компоненти во Spring комуницираат на овој начин, направивме custom имплементација на овој шаблон за ова сценарио.
     302{{{#!java
     303public abstract class EmailEvent extends ApplicationEvent {
     304    protected EventType eventType;
     305    protected User user;
     306    protected String subject;
     307    protected String message;
     308
     309    public EmailEvent(User user) {
     310        super(user);
     311        this.user = user;
     312    }
     313
     314    public User getUser() {
     315        return user;
     316    }
     317
     318    public void setUser(User user) {
     319        this.user = user;
     320    }
     321
     322    public EventType getEventType() {
     323        return eventType;
     324    }
     325
     326    public void setEventType(EventType eventType) {
     327        this.eventType = eventType;
     328    }
     329
     330    public String getSubject() {
     331        return subject;
     332    }
     333
     334    public void setSubject(String subject) {
     335        this.subject = subject;
     336    }
     337
     338    public String getMessage() {
     339        return message;
     340    }
     341
     342    public void setMessage(String message) {
     343        this.message = message;
     344    }
     345}
     346}}}
     347Имено, при регистрација на нов корисник, нова резервација, одобрување на профил или фирма се исплаува соодветен настан, објект кој наследува од EmailEvent и во конструкторот се справува со subject и message зависнот од типот. Овој настан го пречекува новодефнираниот listener и соодветно се извршува логиката за испраќање на порака.
     348{{{#!java
     349public class OnRegistrationSuccessEvent extends EmailEvent {
     350    private static final long serialVersionUID = 1L;
     351    private User user;
     352
     353    public OnRegistrationSuccessEvent(User user) {
     354        super(user);
     355        this.eventType = EventType.REGISTRATION;
     356        this.subject = "TourMate - Успешна регистрација";
     357        this.message = "Драг кориснику,\n\nВе известуваме дека Вашата регистрација на апликацијата TourMate е успешна. За да можете да го користите профилот, потребно е истиот да е одобрен од страна на администраторот за што ќе добиете дополнителна потврда на оваа адреса.\n\n\nСо почит,\nTourMate";
     358    }
     359}
     360}}}
     361{{{#!java
     362    @Override
     363    @Transactional
     364    public void approveUserProfile(User u) {
     365        u.setEnabled(true);
     366        em.persist(u);
     367        eventPublisher.publishEvent(new OnProfileEnabledEvent(u));
     368    }
     369}}}
     370{{{#!java
     371@Component
     372public class RegistrationEmailListener implements ApplicationListener<EmailEvent> {
     373
     374    @Autowired
     375    private Environment environment;
     376    @Autowired
     377    private MailingService mailingService;
     378    @Override
     379    public void onApplicationEvent(EmailEvent event) {
     380        mailingService.sendMail(event.getUser().getEmail(), event.getSubject(), event.getMessage());
     381    }
     382}
     383}}}
     384=== Листа сместувања
     385Мала промена има во приказот на резултатите од ова корисничко сценарио. Врз основа на некои основни статистики, хотелите кои во дадениот период се наоѓаат во топ 5 според бројот на резервации се означени со беџ „Најпопуларен“ и позадина во друга боја, додека пак оние кои имаат малку или немаат воопшто резервација, добиваат случајно една од ознаките „специјална цена“, „последна соба“ или „достапно само денес“ како извесен кавзи-маркетиншки трик.
     386Промена за ова е направена само во сервисот кој го враќа DTO-от за хотелот, каде се додадени проверки за тоа во која категорија припаѓа хотелот.
     387{{{#!java
     388    @Override
     389    public List<HotelDto> getRoomsAvailibilityByDateAndLocation(String hotelLocation, Date dateFrom, Date dateTo, int numberOfBeds, Boolean flexible) {
     390        long numberOfNights = Duration.between(dateFrom.toInstant(), dateTo.toInstant()).toDays();
     391        List<Hotels> hotels = getHotelsByLocation(hotelLocation);
     392        List<HotelRoomReservations> hotelRoomReservations = getReservationsInPeriod(hotelLocation, dateFrom, dateTo);
     393        List<Hotels> hotelsWithReservations = hotelRoomReservations.stream().map(x -> x.getHotelRoom().getHotel()).toList();
     394        List<Hotels> mostReservedHotels = hotelRoomReservations.stream()
     395                .collect(Collectors.groupingBy(x -> x.getHotelRoom().getHotel(), Collectors.counting())).entrySet().stream()
     396                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
     397                .limit(5)
     398                .map(Map.Entry::getKey)
     399                .toList();
     400        List<Hotels> leastReservedHotels = hotelRoomReservations.stream()
     401                .collect(Collectors.groupingBy(x -> x.getHotelRoom().getHotel(), Collectors.counting())).entrySet().stream()
     402                .sorted(Map.Entry.comparingByValue())
     403                .limit(5)
     404                .map(Map.Entry::getKey)
     405                .toList();
     406        List<Hotels> hotelsWithoutReservations = hotels.stream().filter(x -> !hotelsWithReservations.contains(x)).toList();
     407        List<Hotels> hotelsToBeMarketed = new ArrayList<>();
     408        hotelsToBeMarketed.addAll(hotelsWithoutReservations);
     409        hotelsToBeMarketed.addAll(leastReservedHotels);
     410        List<HotelRoomAvailable> roomsAvailible = hotelDao.getRoomsAvailibilityByDateAndLocation(hotelLocation, dateFrom, dateTo, numberOfBeds, flexible);
     411        Map<Hotels, List<HotelRoomAvailable>> roomsByHotels = roomsAvailible.stream().collect(Collectors.groupingBy(x -> x.getHotelRoom().getHotel()));
     412        List<HotelDto> hotelsList = roomsByHotels.keySet().stream()
     413                .map(x -> new HotelDto(
     414                        x.getHotelId(),
     415                        x.getHotelName(),
     416                        x.getHotelDescripiton(),
     417                        x.getHotelLocation(),
     418                        x.getHotelEDBS(),
     419                        x.getParking(),
     420                        x.getPetFriendly(),
     421                        x.getInternetAvailable(),
     422                        roomsByHotels.get(x).stream().mapToDouble(y -> y.getHotelRoom().getPrice()).min().getAsDouble() * numberOfNights,
     423                        roomsByHotels.get(x),
     424                        getReviewsForHotel(x.getHotelId()),
     425                        getReviewsForHotel(x.getHotelId()).stream().mapToDouble(Reviews::getNumStar).average().orElse(0),
     426                        getHotelImages(x.getHotelId()),
     427                        mostReservedHotels.contains(x),
     428                        hotelsToBeMarketed.contains(x)
     429                )).toList();
     430        return hotelsList;
     431    }
     432}}}