wiki:UseCaseImplementations

Version 8 (modified by 211255, 4 months ago) ( diff )

--

Имплементација на кориснички сценарија

Општи информации

Нашата апликација, како што е наведено и во претходните фази, се темели на клиент-сервер архитектура. Во овој случај клиентската страна е „претставена“ преку React апликација, додека пак серверската страна е Spring Boot апликација. Во основа на оваа архитектура е комуникација меѓу клиентот и серверот преку HTTP барања. За визуелизација и давање можност за интеракција на крајниот корисник, кој управува директно со апликацијата на клиентска страна, беше потребно да воспоставуваме конекција и соодветно да ги обработуваме простите податоци кои пристигнуваат од серверската страна. Ова го постигнавме преку Axios HTTP клиентот кој е инсталиран на клиенстката апликација и неговата инстанца во продолжение е онаа преку која ги испраќаме сите барања до серверот.

Error: Failed to load processor javascript
No macro or processor named 'javascript' found

На овој начин обезбедуваме при секое барање основниот URL да биде основниот URL на серверската апликација, додека пак со поставување на параметарот withCredentials овозможуваме препраќање на колачињата и XMLHttpRequest, што овозможува прибавување на нови податоци без целосно одновно вчитување на страницата.

Custom React Hook-и

За поедноставно справување со HTTP GET и POST барањата, кои како што претходно споменавме се главната врска меѓу клиентската и серверската страна и практично не е можно да постои компонента каде не се употребуваат, креиравме наши React Hook-и кои се реискористливи и можат да се употребуваат во различни сценарија со едноставна промена на URL-то

useGet

Error: Failed to load processor javascript
No macro or processor named 'javascript' found

Како што и самото име кажува, овој Hook го користиме за GET барања кон серверската страна. При инстанцирање се наведува URL кон кое се праќаат барањата. За чување на податоците кои се добиваат како одговор се користи концептот на useState од React што овозможува ререндерирање на сите компоненти при промена на состојбата на објектот. На сличен начин се постапува и со знаменцето за вчитување на податоци, кое при испраќање на барањето се поставува на true, додека пак кога ќе заврши обработката се враќа на false. Истото служи како guard clause за компонентите кои ги користат податоците кои се чекаат од GET барањето, како би се избегнале исклучоци во случај кога рендерирањето на компонентата ќе заврши пред податоците да бидат вчитани. Асинхроната функција која ги прибавува податоците од серверот е ставена во useEffect callback, што овозможува нејзино реизвршување при промена на некој од елементите во низата зависности. Овој концепт го искористивме за да овозможиме на едноставен начин ререднерирање на компонентите во кои додаваме нови записи, преку вметнување на дополнителна вредност/состојба changed во низата зависноти која пак, при праќање на барање кое очекуваме да предизвика промена на податоците достапни на страницата, се менува и со тоа автоматски се испраќа ново GET барање и промените се одразуваат на компонените кои се зависни од нив. GET барањето испратено преку Axios HTTP клиентот враќа Promise со кој соодветно се справуваме на горенаведениот начин:

  • во then сегментот состојбата на data се поставува на податоците кои се вратени од серверот (ова значи дека барањето поминало со статус 200);
  • catch сегментот се извршува кога одговорот на барањето е со статус 4ХХ, односно грешка, па во овој случај корисникот се пренасочува до страница со грешка
  • finally сегментот се извршува во секој случај, односно означува дека комуникацијата е завршена, вратен е одговор од серверот, па тука се поставува знаменцето isLoading назад на false

usePost

Error: Failed to load processor javascript
No macro or processor named 'javascript' found

Овој Hook го користиме за POST барања кон серверската страна. Од него постојат неколку модифицирани верзии во зависоност од тоа дали парамтерите се испраќаат во телото на барањето, како URL параметри или како променливи во патеката, но во основа се работи за иста имплементација. За разлика од useGet, тука, URL-то се испраќа како аргумент на функцијата, заедно со податоците кои треба да се испратат како параметри и состојбата на зависната променлива за која зборувавме во претходната компонент. Откако ќе се испрати POST, se враќа Promise со кој соодветно се справуваме на горенаведениот начин, со единствна разлика што во then сегментот, кога статусот означува успех, ја менуваме состојбата на зависната променлива за да се ререндерираат зависните компоненти.

useFormData

Error: Failed to load processor javascript
No macro or processor named 'javascript' found

Во секој формулар каде што имаме кориснички влез потребно е да се справиме со него и да го проследиме до серверот во утврдената форма. Ова може да се постигне на стариот добар начин, со користење на концептот useState од React и посебна состојба за секое од input полињата. За да го поедноставиме ова, успешно имплементиравме општа функција за справување со корисничкиот влез која работи на следниот начин. Наместо посебни состојби за секое поле, чуваме состојба на еден објект, каде клучот е соодветно name атрибутот на полето, а вредноста е неговиот value. За процесирање на текстуалните полиња, при промена на вредноста одговорна е функцијата onFormChange, каде се менува состојбата на записот од објектот кој е засегнат според name атрибутот. Оваа функција се извршува на секој onChange настан испален од било која input компонента. onCheckBoxChange е ништо повеќе од специјална имплементација на onFormChange функцијата за checkbox input. Како и во претходно наведените Hook-и, и тука, референци до функциите и состојбите кои треба да бидат пристапени од другите компоненти се враќаат од функцијата.

Имплементација

Се најавува на системот

Се регистрира на системот

Корисник со основни привилегии

Листа сместувања

public List<HotelRoomAvailable> 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();
        }
    }

Ова е кверито од кое се зимаат хотелите по криетриум, каде што првиот дел е додека флексибилноста од 3 дена има вредност true, па тогаш се листаат +/- (1,2,3) дена од бараните критериуми, а доколку има вредност false тогаш се листаат според точните дати кои се внесени.

public List<HotelDto> getRoomsAvailibilityByDateAndLocation(String hotelLocation, Date dateFrom, Date dateTo, int numberOfBeds, Boolean flexible) {
        long numberOfNights = Duration.between(dateFrom.toInstant(), dateTo.toInstant()).toDays();
        List<HotelRoomAvailable> roomsAvailible = hotelDao.getRoomsAvailibilityByDateAndLocation(hotelLocation, dateFrom, dateTo, numberOfBeds, flexible);
        Map<Hotels, List<HotelRoomAvailable>> roomsByHotels = roomsAvailible.stream().collect(Collectors.groupingBy(x -> x.getHotelRoom().getHotel()));
        List<HotelDto> hotelsList = roomsByHotels.keySet().stream()
                .map(x -> new HotelDto(
                        x.getHotelId(),
                        x.getHotelName(),
                        x.getHotelDescripiton(),
                        x.getHotelLocation(),
                        x.getHotelEDBS(),
                        x.getParking(),
                        x.getPetFriendly(),
                        x.getInternetAvailable(),
                        roomsByHotels.get(x).stream().mapToDouble(y -> y.getHotelRoom().getPrice()).min().getAsDouble() * numberOfNights,
                        roomsByHotels.get(x),
                        getReviewsForHotel(x.getHotelId()),
                        getReviewsForHotel(x.getHotelId()).stream().mapToDouble(Reviews::getNumStar).average().orElse(0),
                        getHotelImages(x.getHotelId())
                )).toList();
        return hotelsList;
    }

Во сервисот за да не ги користиме сите податоци од вистинската класа користиме класа HotelDto односно data transfer object. Со ова овозможуваме да за пренос на податоци меѓу backend и frontend. Во функцијата ги листаме сите слободни соби од сите хотели со наведените криетриуми.

@GetMapping(path = "/hotel/search")
    public List<HotelDto> searchAvailibleRooms(@RequestParam(name = "hotelLocation") String hotelLocation,
                                               @RequestParam(name = "dateFrom") @DateTimeFormat(pattern = "yyyy-MM-dd") Date dateFrom,
                                               @RequestParam(name = "dateTo") @DateTimeFormat(pattern = "yyyy-MM-dd") Date dateTo,
                                               @RequestParam(name = "numBeds") int numBeds,
                                               @RequestParam(name = "flexible") Boolean flexible)
    {
        return hotelManager.getRoomsAvailibilityByDateAndLocation(hotelLocation, dateFrom, dateTo, numBeds, flexible);
    }

Контролерот ги прима потребните податоци и ја повикува функцијата од сервисот.

Листа ресторани

public List<RestaurantsAvailible> getTablesByDateAndLocation(String restaurantLocation, Date hourFrom, Date hourTo, int noSeats){
        return em.createQuery("select hr from RestaurantsAvailible hr where hr.hourFrom <= :hourFrom and hr.hourTo >= :hourTo " +
                        "and hr.restaurantTable.restaurant.restaurantLocation LIKE :restaurantLocation and hr.restaurantTable.noSeats >= :noSeats")
                .setParameter("restaurantLocation", restaurantLocation)
                .setParameter("hourFrom", hourFrom)
                .setParameter("hourTo", hourTo)
                .setParameter("noSeats", noSeats)
                .getResultList();
    }

Ова е кверито кое ги листа сите маси во одредена локација, со одредено време на доаѓање, заминување и бројка колку луѓе ќе дојдат.

public List<RestaurantDto> getTablesByDateAndLocation(String restaurantLocation, Date date, String hourFrom, String hourTo, int noSeats) {
        Date dateFrom = date;
        Date dateTo = Date.from(date.toInstant());
        String[] splittedFrom = hourFrom.split(":");
        String[] splittedTo = hourTo.split(":");
        dateFrom.setHours(Integer.parseInt(splittedFrom[0]));
        dateFrom.setMinutes(Integer.parseInt(splittedFrom[1]));
        dateTo.setHours(Integer.parseInt(splittedTo[0]));
        dateTo.setMinutes(Integer.parseInt(splittedTo[1]));
        
        List<RestaurantsAvailible> restaurantsAvailibles = restaurantDao.getTablesByDateAndLocation(restaurantLocation, hourFrom, hourTo, noSeats);
        Map<Restaurant, List<RestaurantsAvailible>> tablesByRestaurants = restaurantsAvailibles.stream().collect(Collectors.groupingBy(x -> x.getRestaurantTable().getRestaurant()));
        List<RestaurantDto> restaurantsList = tablesByRestaurants.keySet().stream()
                .map(x -> new RestaurantDto(
                        x.getRestaurantID(),
                        x.getRestaurantName(),
                        x.getRestaurantLocation(),
                        x.getCousineType(),
                        x.getRestaurantDescription(),
                        x.getRestaurantEdbs(),
                        x.getMenus(),
                        tablesByRestaurants.get(x),
                        getReviewsForRestaurant(x.getRestaurantID()),
                        getReviewsForRestaurant(x.getRestaurantID()).stream().mapToDouble(Reviews::getNumStar).average().orElse(0),
                        getRestaurantImages(x.getRestaurantID()),
                        getMenuImagesByRestaurant(x.getRestaurantID())
                )).toList();
        return restaurantsList;
    }

Сервисот кој исто како и во хотели користи Dto притоа ги листа сите ресторани кои можат да го опслужат барањето од корисниците. Со тоа што времето од-до се интерпретира како текст, па тие ги средуваме во сервисот.

@GetMapping(path = "/restaurant/search")
    public List<RestaurantDto> searchAvailableRestaurant(@RequestParam(name = "restaurantLocation") String restaurantLocation,
                                                         @RequestParam(name = "date") @DateTimeFormat(pattern = "yyyy-MM-dd") Date date,
                                                         @RequestParam(name = "hourFrom") String hourFrom,
                                                         @RequestParam(name = "hourTo") String hourTo,
                                                         @RequestParam(name = "numPeople") int noSeats) {

        return restaurantManager.getTablesByDateAndLocation(restaurantLocation, date, dateFrom, dateTo, noSeats);
    }

Во контролерот се примаат податоци за локација, датум, време од до во форма на текст и број на седишта

Листа превоз

public List<TransportRoute> getTransportsAvailableByFilters(String fromL, String toL, Date date, int numPassengers) {
        return em.createQuery("select h from TransportRoute h where h.from = :froml and h.to = :tol and h.freeSpace >= :nump")
                .setParameter("froml", fromL)
                .setParameter("tol", toL)
                .setParameter("nump", numPassengers)
                .getResultList();
    }

Ова е кверито со кое се наоѓаат сите слобдни транспорти со одредена дата од-до одредено место и број на патници

public List<TransportListingDto> getTransportsAvailableByFilters(String from, String to, Date date, int numPassengers) {
        List<TransportRoute> transportAvailable = transportDao.getTransportsAvailableByFilters(from, to, date, numPassengers);
        Map<TransportAvailible, List<TransportRoute>> transportsByTransporter = transportAvailable.stream().collect(Collectors.groupingBy(x -> x.getParentRoute()));
        List<TransportListingDto> transportList = transportsByTransporter.keySet().stream().toList().stream()
                .map(x -> new TransportListingDto(
                        x.getTransportAvailibleId(),
                        x.getFrom(),
                        x.getTo(),
                        x.getDate(),
                        x.getFreeSpace(),
                        x.getTime(),
                        transportsByTransporter.get(x).stream().mapToDouble(y -> y.getPrice()).min().getAsDouble(),
                        x.getRoutes(),
                        x.getTransport(),
                        getReviewsForTransport(x.getTransport().getTransportID()),
                        getReviewsForTransport(x.getTransport().getTransportID()).stream().mapToDouble(Reviews::getNumStar).average().orElse(0)
                )).collect(Collectors.toList());
        return transportList;
    }

Исто како и останатите имаме Dto и ги листаме сите слобдони транспорти со наведените критериуми. Притоа што доколку се внесе некој град кој е попатен во некоја рута се листа и таа со тоа што се зима главната рута на тој град.

@GetMapping(path = "/transport/search")
    public List<TransportListingDto> searchAvailableTransport(@RequestParam(name = "from") String from,
                                                              @RequestParam(name = "to") String to,
                                                              @RequestParam(name = "date") @DateTimeFormat(pattern = "yyyy-MM-dd") Date date,
                                                              @RequestParam(name = "numPassengers") int numPassengers){
        return transportManager.getTransportsAvailableByFilters(from, to, date, numPassengers);
    }

Контролерот кој според влезните критериуми ги листаме сите слобдони транспорти за тие дестинации.

Најавен давател на услуги

Регистра бизнис


    public void createBusiness(Business business) {
        em.persist(business);
    }

Се креира нов бизнис во база

    public void createBusiness(Business business, long userId) {
        User u = usersManager.findUserByID(userId);
        business.setUser(u);
        businessDao.createBusiness(business);
    }

Креирање бизнис во сервисот, каде што се наоѓа корисникот кој сака да го креира

@PostMapping(path = "/business/add")
    public void addBusiness(@RequestBody Business business, @RequestParam(name = "userId") long userId)
    {
        businessManager.createBusiness(business, userId);
    }

Контролерот каде се зима цел објект бизнис од Frontend, па се повикува функцијата од сервисот

Додава хотел




public void createHotel(Hotels hotel) {
        em.persist(hotel);
    }

Се креира нов хотел во база

public void createHotel(Hotels hotels, long userId) {
        User u = usersManager.findUserByID(userId);
        hotels.setOwner(u);
        hotelDao.createHotel(hotels);
    }

Во сервисот се наоѓа корисникот кој сака да отвори хотел, и истиот се сетира за поседител на хотелот

@PostMapping(path = "/hotel/add")
    public void add(@RequestBody Hotels hotel, @RequestParam(name = "userId") long userId) {
        hotelManager.createHotel(hotel, userId);
    }

Хотелот се зима како цел објект преку frontend и се зима id на user и се повикува функцијата од сервисот

Додава соба во хотел



public void createRoom(HotelRoom hotelRoom) {
        em.persist(hotelRoom);
    }

Се крериа нова соба за одреден хотел

public void createRoom(Long hotel, String hotelRoomDescription, String hotelRoomName, Boolean kitchenAvailable, Boolean airConditioning, Boolean balcony, double price, int numOfBeds) {
        Hotel hotel = findHotelByID(hotel);
        HotelRoom hotelRoom = new HotelRoom(hotel, hotelRoomDescription, hotelRoomName, kitchenAvailable, airConditioning, balcony, price, numOfBeds);
        hotelDao.createRoom(hotelRoom);
    }

Се креира нова соба во сервисот притоа што се зима id на хотелот на кој ќе се креира новата соба

@PostMapping(path = "/hotel/rooms/add")
    public void addRoom(@RequestBody HotelRoom room,
                        @RequestParam(name = "hotelId") long hotelId) {
        hotelManager.createRoom(hotelId, room.getHotelRoomDescription(), room.getHotelRoomName(), room.getKitchenAvailable(), room.getAirConditioning(), room.getBalcony(), room.getPrice(), room.getNumOfBeds());
    }

Во контролерот се зима цел објект HotelRoom и се зима id на хотелот и се повикува функцијата за креирање соба од сервисот


public void createRoomAvailible(HotelRoomAvailable hra) {
        em.persist(hra);
    }

Се креира слободна соба за хотелот во база

public void createRoomAvailible(Long id, Date dateFrom, Date dateTo, int numberOfBeds) {
        HotelRoom hotelRoom = findRoomById(id);
        HotelRoomAvailable hra = new HotelRoomAvailable(hotelRoom, dateFrom, dateTo, numberOfBeds);
        hotelDao.createRoomAvailible(hra);
    }

Во сервисот се зима претходно креирана соба и се креира нов објект од тип HotelRoomAVailable кој чува за која соба од кога до кога е слободна

@PostMapping(path = "/hotel/rooms/available/{id}/add")
    public void addRoomAvailible(@RequestBody HotelRoomAvailable hotelRoomAvailable,
                                 @PathVariable long id)
    {
        hotelManager.createRoomAvailible(id, hotelRoomAvailable.getDateFrom(), hotelRoomAvailable.getDateTo(), hotelRoomAvailable.getNumberOfBeds());
    }

Во контролерот се повикува функцијата од сервисот за креирање на соба, а прима цел објект од типот преку frontend и id за која соба станува збор


public void editRoomAvailible(long hotelRoomAvailableId, HotelRoom hotelRoom, Date dateFrom, Date dateTo, int numberOfBeds) {
        HotelRoomAvailable hr = findAvailibleRoomById(hotelRoomAvailableId);
        hr.setHotelRoom(hotelRoom);
        hr.setDateFrom(dateFrom);
        hr.setDateTo(dateTo);
        hr.setNumberOfBeds(numberOfBeds);
        hotelDao.createRoomAvailible(hr);
    }

Креирањето и менувањето во база е исто затоа не се наведува, а во сервисот се менуваат сите ново наведени детали за самата соба

@PostMapping(path = "/hotel/rooms/available/edit")
    public void editRoomAvailible(@RequestBody HotelRoomAvailable hotelRoomAvailable)
    {
        hotelManager.editRoomAvailible(hotelRoomAvailable.getHotelRoomAvailableId(), hotelRoomAvailable.getHotelRoom(), hotelRoomAvailable.getDateFrom(), hotelRoomAvailable.getDateTo(), hotelRoomAvailable.getNumberOfBeds());
    }

Во Котнтролерот се зима цел објект за слободната соба и таа се повикува функцијата од сервисот


public List<HotelRoomReservations> findReservationByHotel(Hotels hotel) {
        List<HotelRoom> hotelRooms = getRoomsOfHotel(hotel);
        return em.createQuery("select hr from HotelRoomReservations hr where hr.hotelRoom.hotel = :hotel").setParameter("hotel", hotel).getResultList();
    }

Се зимаат сите резервации за одреден хотел од база

public List<HotelReservationDto> findVaidReseravtionsByHotel(Long hotelId) {
        Hotels hotel = findHotelByID(hotelId);
        List<HotelRoomReservations> reservations = hotelDao.findReservationByHotel(hotel);
        return reservations.stream()
                .map(x -> new HotelReservationDto(
                        x.getUser(),
                        x.getHotelRoom(),
                        x.getDateFrom(),
                        x.getDateTo(),
                        x.getNumberOfBeds()
                )).toList();
    }

Исто како и претходно се користи Dto со кој се па се враќаат сите резервации за одреден хотел

@GetMapping(path = "/hotel/{id}/reservations/active")
    public List<HotelReservationDto> getActiveReservationsForHotel(@PathVariable Long id)
    {
        return hotelManager.findVaidReseravtionsByHotel(id);
    }

Се праќа само id на хотелот и во сервисот се прави логиката.

Менува хотел


public void editHotel(long hotelId, String hotelName, String hotelDescripiton, String hotelLocation, String hotelEDBS, Boolean parking, Boolean petFriendly, Boolean internetAvailable) {
        Hotels hotel = hotelDao.findHotelByID(hotelId);
        hotel.setHotelName(hotelName);
        hotel.setHotelDescripiton(hotelDescripiton);
        hotel.setHotelLocation(hotelLocation);
        hotel.setHotelEDBS(hotelEDBS);
        hotel.setParking(parking);
        hotel.setPetFriendly(petFriendly);
        hotel.setInternetAvailable(internetAvailable);
        hotelDao.editHotel(hotel);
    }

Зачувување во база е исто како и креирање притоа што не го покажуваме, а менувањето на хотел во сервисот ги менува сите потребни детали за истиот

@PostMapping(path = "/hotel/edit")
    public void edit(@RequestBody Hotels hotel)
    {
        hotelManager.editHotel(hotel.getHotelId(), hotel.getHotelName(), hotel.getHotelDescripiton(), hotel.getHotelLocation(), hotel.getHotelEDBS(), hotel.getParking(), hotel.getPetFriendly(), hotel.getInternetAvailable());
    }

Во контролерот се зима цел објект преку frontend и истиот се препраќа во функцијата од сервисот

Додава ресторан



No image "MyResourcesRestaurantAdd.png" attached to UseCaseImplementations

public void createRestaurant(Restaurant restaurant) {
        em.persist(restaurant);
    }

Се креира ресторан во базата

public void createRestaurant(Restaurant restaurant, long userId) {
        User u = usersManager.findUserByID(userId);
        Restaurant r = new Restaurant(restaurant.getRestaurantName(), restaurant.getRestaurantLocation(), restaurant.getCousineType(), restaurant.getRestaurantDescription(), restaurant.getRestaurantEdbs(), u);
        restaurantDao.createRestaurant(r);
    }

Во сервисот се наоѓа корисникот кој го креира и се става ресторанот под негово име

@PostMapping(path = "/restaurant/add")
    public void add(@RequestBody Restaurant restaurant, @RequestParam(name = "userId") long userId) {

        restaurantManager.createRestaurant(restaurant, userId);
    }

Во контролерот се зима ресторанот како цел објект и id на корисникот кој го креира, па се повикува функцијата за креирање ресторан од сервисот

Менува ресторан

public void editRestaurant(long restaurantID, String restaurantName, String restaurantLocation, String cousineType, String restaurantDescription, String restaurantEdbs, User restaurantOwner) {
        Restaurant res = findRestaurantByID(restaurantID);
        res.setRestaurantName(restaurantName);
        res.setRestaurantLocation(restaurantLocation);
        res.setRestaurantEdbs(restaurantEdbs);
        res.setRestaurantDescription(restaurantDescription);
        res.setRestaurantOwner(restaurantOwner);
        res.setCousineType(cousineType);
        restaurantDao.createRestaurant(res);
    }

Исто е креирање и менување на ресторан во база, затоа не го покажуваме. Во сервисот се зима ресторанот и се менуваат сите негови детали што поседителот ги изменил

@PostMapping(path = "/restaurant/edit")
    public List<Restaurant> edit(@RequestBody Restaurant restaurant) {
        restaurantManager.editRestaurant(restaurant.getRestaurantID(), restaurant.getRestaurantName(), restaurant.getRestaurantLocation(), restaurant.getCousineType(), restaurant.getRestaurantDescription(), restaurant.getRestaurantEdbs(), restaurant.getRestaurantOwner());
        return restaurantManager.getRestaurants();
    }

Во контролерот се зима целиот ресторан како објект од frontend и тој се препраќа во сервисот

Додава мени



public void addMenuToRestaurant(Menu menu) {
        em.persist(menu);
    }

Менито се зачувува во база

public void addMenuToRestaurant(long restaurantId, Menu menu) {
        Restaurant r = findRestaurantByID(restaurantId);
        menu.setRestaurant(r);
        restaurantDao.addMenuToRestaurant(menu);
    }

Во сервисот се ноѓа ресторанот на кого ќе се додава нова ставка од менито и истото се додава

@PostMapping(path = "/restaurant/{id}/menu/add")
    public void addMenu(@PathVariable(name = "id") long restaurantId, @RequestBody Menu menu) {
        restaurantManager.addMenuToRestaurant(restaurantId, menu);
    }

Во котрнолерот се зима id на ресторан и цел објект од менито, и истото се препраќа на сервисот да ја прави логиката


public void editMenu(long menuId, String name, String ingredients, double price) {
        Menu menu = findMenuById(menuId);
        menu.setName(name);
        menu.setIngredients(ingredients);
        menu.setPrice(price);
        menuDao.editMenu(menu);
    }

Повторно дека менување и креирање е исто не се покажува тој дел. Во сервисот се зима менито според id и истото се менува според новите детали кои се внесени

@PostMapping(path = "/menu/{id}/edit")
    public void editMenu(@PathVariable Long id,
                         @RequestParam String name,
                         @RequestParam String ingredients,
                         @RequestParam double price)
    {
        menuManager.editMenu(id, name, ingredients, price);
    }

Контролерот прима id од менито и негови нови детали кои ги предава на сервисот да ја доврши логиката

Додава маси


public void saveTable(RestaurantsTable resTable) {
        em.persist(resTable);
    }

Додавање на нова маса во базата

public void createTable(Long restaurantId, int noSeats) {
        Restaurant r = restaurantDao.findRestaurantByID(restaurantId);
        RestaurantsTable restaurantsTable = new RestaurantsTable(r, noSeats);
        restaurantDao.saveTable(restaurantsTable);
    }

Во сервисот се зима ресторанот на кој ќе се додава новата маса, за неа се внесуваат број на седишта

@PostMapping(path = "/restaurant/table/{id}/add")
    public void addTable(@PathVariable Long id, @RequestParam Integer noSeats) {
        restaurantManager.createTable(id, noSeats);
    }

Се зима id на ресторанот и бројот за колку луѓе е наменета масата, па се повикува функцијата од сервисот за понатамошна логика


public void saveTableAvailable(RestaurantsAvailible ra){
        em.persist(ra);
    }

Се зачувува слободната маса во база

public void createTableAvailable(Long rt, Date hourFrom, Date hourTo, int numTables) {
        RestaurantsTable rtabl = findTableById(rt);
        RestaurantsAvailible ra = new RestaurantsAvailible(rtabl, hourFrom, hourTo, numTables);
        restaurantDao.saveTableAvailable(ra);
    }

Во сервисот се зима масата преку id и се прави нов објект од расположливост на маси и се сетира од кога до кога и колку такви маси има на располагање

@PostMapping(path = "/restaurant/table/{id}/available/add")
    public void addTableAvailable(@RequestBody RestaurantsAvailible restaurantsAvailible,
                                  @PathVariable Long id) {
        restaurantManager.createTableAvailable(id, restaurantsAvailible.getHourFrom(), restaurantsAvailible.getHourTo(), restaurantsAvailible.getNumTables());
    }

За додавање на расположливост во контролерот се зима објект од RestaurantsAvailable и се зима id од која маса


public void editTable(Restaurant restaurant, long tableId, int noSeats) {
        RestaurantsTable resTable = findTableById(tableId);
        resTable.setRestaurant(restaurant);
        resTable.setNoSeats(noSeats);
        restaurantDao.saveTable(resTable);
    }

Се наоѓа масата преку id и на истата се додава се менуваат потребните детали. Зачувувањето во база е исто па не се покажува

@PostMapping(path = "/restaurant/table/edit")
    public void editTable(@RequestBody RestaurantsTable restaurantsTable) {
        restaurantManager.editTable(restaurantsTable.getRestaurant(), restaurantsTable.getTableId(), restaurantsTable.getNoSeats());
    }

Се зима цел објект од масата и за истата се пропушта на сервисот за логиката


public List<RestaurantReservations> findReservationByRestaurant(Restaurant restaurant) {
        return em.createQuery("select rr from RestaurantReservations rr where rr.table.restaurant = :rest").setParameter("rest", restaurant).getResultList();
    }

Се листаат сите резервации кои се резервирани на ресторанот

public List<RestaurantReservationDto> findReservationByRestaurant(Long restaurant) {
        Restaurant r = findRestaurantByID(restaurant);
        List<RestaurantReservations> res = restaurantDao.findReservationByRestaurant(r);
        return res.stream().map(x -> new RestaurantReservationDto(
                x.getUser(),
                x.getTable(),
                x.getTimeFrom(),
                x.getTimeTo()
        )).collect(Collectors.toList());
    }

Исто како и горе се прави Dto и се ноѓаат сите резервации од конкретниот ресторан и истите се враќаат како резултатна листа

@GetMapping(path = "/restaurant/{id}/reservations/active")
    public List<RestaurantReservationDto> getActiveReservationsForRestaurant(@PathVariable Long id)
    {
        return restaurantManager.findReservationByRestaurant(id);
    }

Преку контролерот се зимаат податоци за id на на ресторанот и потоа се повикува функцијата од сервисот за резервација.

Додава транспорт

При додавање на транспорт, има форма во која може да се внесат детали за транпосртот.





Истиот тој транспорт може да се изменува по потреба


Додава рути

Секој транпосрт може да нуди различни рути, од кој до кој град патува патува и попатните градови низ кој поминува. За истите се додава и цена на чинење за секоја релација





Покрај додавањето има опција и да се прегледуваат резервациите кои ги има одреден транспорт


Најавен администратор

Администраторот има улога да ги управува профилите, односно да ги одборува, а истото важи и за фирмите.

Управување со профили

Управува со фирми

Најавен корисник на услуги

Откога корисникот ќе се реши за некоја понуда, тој може да ги види деталите за истата. При резервација на услугата се добива порака за успешна резервација.

Резеревација ресторан



Резервира транспорт



Резервира хотел


Откажува услуга

Корисникот кој ги закажува резервациите има можност да ги прегледува истите. Има резервации кои се активни, односно што следат, но има и претходни резервации за кои може да остави некакво мислење


Attachments (53)

Note: See TracWiki for help on using the wiki.