\documentclass{article}
\usepackage{fontspec}
\usepackage{polyglossia}
\usepackage{geometry}
\usepackage{graphicx}
\usepackage{minted}
\usepackage{xcolor}
\usepackage{hyperref}
\usepackage{tabularx}
\usepackage{enumitem}

% Ustawienia języka polskiego
\setmainlanguage{polish}
\setotherlanguage{english}

\setlength{\parindent}{0pt}
\renewcommand{\baselinestretch}{1.2}

\geometry{a4paper, margin=2.5cm}

% Ustawienia dla pakietu minted
\usemintedstyle{vs}
\setminted{
    fontsize=\normalsize,
    breaklines=true,
    breakanywhere=true,
    frame=single,
    framesep=2mm,
    linenos=true,
    tabsize=2
}

\begin{document}

    \begin{center}
    {\LARGE \textbf{ZTBD - sprawozdanie z projektu}}
        \\[1.5em]
        {\large 2025-05-24}\\[2em]
    \end{center}

    \section*{Podstawowe informacje}

    \begin{tabular}{ll}
        \textbf{Autorzy projektu:}       & Mikołaj Kaczmarek (124942) \\
        & Piotr Wilma (124832)       \\
        \textbf{Temat:}                  & Hotel                      \\
        \textbf{Wybrany zakres (ocena):} & 5,0                        \\
        \textbf{Baza danych:}            & \texttt{ztbd124942}      \\
    \end{tabular}


    \section{Wprowadzenie}

    Projekt obejmuje stworzenie bazy danych MongoDB dla hotelu.
    System zarządzania hotelem wymaga przechowywania danych o gościach, pokojach, rezerwacjach, pracownikach oraz usługach dodatkowych.
    Opracowana baza danych umożliwia śledzenie aktualnego stanu rezerwacji, zarządzanie dostępnością pokoi oraz realizację dodatkowych zamówień gości hotelowych.
    Rozwiązanie takie znajduje zastosowanie w każdym obiekcie hotelowym potrzebującym wszechstronnego systemu do zarządzania codzienną działalnością.

    Główne funkcjonalności realizowane przez bazę danych obejmują:
    \begin{itemize}
        \item Przechowywanie informacji o gościach wraz z ich danymi kontaktowymi
        \item Zarządzanie pokojami hotelowymi i ich atrybutami
        \item Obsługę rezerwacji z informacją o terminach pobytu i statusie płatności
        \item Ewidencję pracowników hotelu z przypisaniem do działów
        \item Katalog usług dodatkowych oraz zamówień na te usługi
    \end{itemize}


    \section{Schemat bazy - kolekcje}

    Opracowana baza danych składa się z 6 kolekcji, łącznie zawierających 30 dokumentów.
    Poniżej przedstawiono szczegółowy opis każdej kolekcji wraz z przykładowymi dokumentami.

    \caption{Struktura bazy danych systemu hotelowego w MongoDB}

    \subsection{Kolekcja: guests}

    \textbf{Opis:} Przechowuje dane gości hotelowych wraz z informacjami kontaktowymi i dodatkowymi atrybutami.

    \textbf{Liczba dokumentów:} 5

    \textbf{Struktura dokumentu:}

    \begin{minted}{javascript}
{
  _id: ObjectId("..."),
  firstName: String,
  lastName: String,
  email: String,
  phoneNumber: String,
  address: {
    street: String,
    city: String,
    postalCode: String,
    country: String
  },
  dateOfBirth: Date,
  loyaltyPoints: Number,
  registrationDate: Date
}
    \end{minted}

    \textbf{Przykładowy dokument:}

    \begin{minted}{javascript}
{
  _id: ObjectId("..."),
  firstName: "Jan",
  lastName: "Kowalski",
  email: "jan.kowalski@email.com",
  phoneNumber: "+48123456789",
  address: {
    street: "Kwiatowa 12",
    city: "Warszawa",
    postalCode: "01-234",
    country: "Polska"
  },
  dateOfBirth: ISODate("1985-05-15T00:00:00Z"),
  loyaltyPoints: 120,
  registrationDate: ISODate("2020-03-10T00:00:00Z")
}
    \end{minted}

    \subsection{Kolekcja: rooms}

    \textbf{Opis:} Zawiera informacje o pokojach hotelowych, ich typach, wyposażeniu i statusie dostępności.

    \textbf{Liczba dokumentów:} 5

    \textbf{Struktura dokumentu:}

    \begin{minted}{javascript}
{
  _id: ObjectId("..."),
  roomNumber: String,
  floor: Number,
  type: String,
  capacity: Number,
  pricePerNight: Number,
  amenities: [String],
  status: String,
  lastRenovation: Date
}
    \end{minted}

    \textbf{Przykładowy dokument:}

    \begin{minted}{javascript}
{
  _id: ObjectId("..."),
  roomNumber: "301",
  floor: 3,
  type: "Suite",
  capacity: 4,
  pricePerNight: 600.00,
  amenities: ["TV", "WiFi", "Minibar", "Klimatyzacja",
             "Sejf", "Ekspres do kawy", "Jacuzzi"],
  status: "Dostępny",
  lastRenovation: ISODate("2022-02-15T00:00:00Z")
}
    \end{minted}

    \subsection{Kolekcja: reservations}

    \textbf{Opis:} Przechowuje informacje o rezerwacjach gości, zawiera referencje do kolekcji guests i rooms.

    \textbf{Liczba dokumentów:} 5

    \textbf{Struktura dokumentu:}

    \begin{minted}{javascript}
{
  _id: ObjectId("..."),
  guestId: ObjectId("..."),
  roomId: ObjectId("..."),
  checkInDate: Date,
  checkOutDate: Date,
  numberOfGuests: Number,
  totalPrice: Number,
  paymentStatus: String,
  specialRequests: [String],
  bookingDate: Date,
  status: String
}
    \end{minted}

    \textbf{Przykładowy dokument:}

    \begin{minted}{javascript}
{
  _id: ObjectId("..."),
  guestId: ObjectId("..."),
  roomId: ObjectId("..."),
  checkInDate: ISODate("2023-05-10T00:00:00Z"),
  checkOutDate: ISODate("2023-05-15T00:00:00Z"),
  numberOfGuests: 2,
  totalPrice: 1250.00,
  paymentStatus: "Opłacone",
  specialRequests: ["Późne zameldowanie", "Dodatkowa poduszka"],
  bookingDate: ISODate("2023-04-15T00:00:00Z"),
  status: "Potwierdzona"
}
    \end{minted}

    \subsection{Kolekcja: employees}

    \textbf{Opis:} Zawiera dane pracowników hotelu wraz z informacjami o stanowisku, wynagrodzeniu i harmonogramie pracy.

    \textbf{Liczba dokumentów:} 5

    \textbf{Struktura dokumentu:}

    \begin{minted}{javascript}
{
  _id: ObjectId("..."),
  firstName: String,
  lastName: String,
  position: String,
  email: String,
  phoneNumber: String,
  dateOfBirth: Date,
  hireDate: Date,
  salary: Number,
  department: String,
  workSchedule: [String],
  address: {
    street: String,
    city: String,
    postalCode: String,
    country: String
  }
}
    \end{minted}

    \textbf{Przykładowy dokument:}

    \begin{minted}{javascript}
{
  _id: ObjectId("..."),
  firstName: "Tomasz",
  lastName: "Nowicki",
  position: "Szef kuchni",
  email: "tomasz.nowicki@hotel.com",
  phoneNumber: "+48567890123",
  dateOfBirth: ISODate("1975-03-10T00:00:00Z"),
  hireDate: ISODate("2018-06-01T00:00:00Z"),
  salary: 7500.00,
  department: "Restauracja",
  workSchedule: ["Poniedziałek", "Wtorek", "Środa", "Niedziela"],
  address: {
    street: "Słoneczna 8",
    city: "Pruszków",
    postalCode: "05-800",
    country: "Polska"
  }
}
    \end{minted}

    \subsection{Kolekcja: services}

    \textbf{Opis:} Zawiera katalog usług dodatkowych oferowanych przez hotel.

    \textbf{Liczba dokumentów:} 5

    \textbf{Struktura dokumentu:}

    \begin{minted}{javascript}
{
  _id: ObjectId("..."),
  name: String,
  description: String,
  price: Number,
  category: String,
  availability: [String],
  location: String,
  requiresReservation: Boolean
}
    \end{minted}

    \textbf{Przykładowy dokument:}

    \begin{minted}{javascript}
{
  _id: ObjectId("..."),
  name: "Masaż relaksacyjny",
  description: "60-minutowy masaż relaksacyjny",
  price: 200.00,
  category: "SPA",
  availability: ["Poniedziałek", "Środa", "Piątek", "Sobota"],
  location: "Hotelowe SPA",
  requiresReservation: true
}
    \end{minted}

    \subsection{Kolekcja: serviceOrders}

    \textbf{Opis:} Przechowuje zamówienia na usługi dodatkowe składane przez gości hotelowych.

    \textbf{Liczba dokumentów:} 5

    \textbf{Struktura dokumentu:}

    \begin{minted}{javascript}
{
  _id: ObjectId("..."),
  guestId: ObjectId("..."),
  reservationId: ObjectId("..."),
  serviceId: ObjectId("..."),
  orderDate: Date,
  quantity: Number,
  totalPrice: Number,
  status: String,
  comments: String
}
    \end{minted}

    \textbf{Przykładowy dokument:}

    \begin{minted}{javascript}
{
  _id: ObjectId("..."),
  guestId: ObjectId("..."),
  reservationId: ObjectId("..."),
  serviceId: ObjectId("..."),
  orderDate: ISODate("2023-06-18T00:00:00Z"),
  quantity: 1,
  totalPrice: 300.00,
  status: "Potwierdzone",
  comments: "Kolacja na 20:00, rocznica ślubu"
}
    \end{minted}


    \section{Referencje między dokumentami}

    W bazie danych zaimplementowano następujące referencje między dokumentami:

    \begin{enumerate}
        \item \textbf{Rezerwacje (reservations) - Goście (guests)}
        \begin{itemize}
            \item Atrybut \texttt{guestId} w kolekcji \texttt{reservations} zawiera referencję do identyfikatora dokumentu z kolekcji \texttt{guests}
            \item Modeluje relację: "Gość dokonuje rezerwacji" (jeden gość może mieć wiele rezerwacji)
        \end{itemize}

        \item \textbf{Rezerwacje (reservations) - Pokoje (rooms)}
        \begin{itemize}
            \item Atrybut \texttt{roomId} w kolekcji \texttt{reservations} zawiera referencję do identyfikatora dokumentu z kolekcji \texttt{rooms}
            \item Modeluje relację: "Rezerwacja dotyczy konkretnego pokoju" (jeden pokój może mieć wiele rezerwacji w różnych terminach)
        \end{itemize}

        \item \textbf{Zamówienia usług (serviceOrders) - Goście (guests)}
        \begin{itemize}
            \item Atrybut \texttt{guestId} w kolekcji \texttt{serviceOrders} zawiera referencję do identyfikatora dokumentu z kolekcji \texttt{guests}
            \item Modeluje relację: "Gość zamawia usługę dodatkową" (jeden gość może złożyć wiele zamówień)
        \end{itemize}

        \item \textbf{Zamówienia usług (serviceOrders) - Rezerwacje (reservations)}
        \begin{itemize}
            \item Atrybut \texttt{reservationId} w kolekcji \texttt{serviceOrders} zawiera referencję do identyfikatora dokumentu z kolekcji \texttt{reservations}
            \item Modeluje relację: "Zamówienie usługi jest przypisane do konkretnej rezerwacji" (jedna rezerwacja może mieć wiele zamówień usług)
        \end{itemize}

        \item \textbf{Zamówienia usług (serviceOrders) - Usługi (services)}
        \begin{itemize}
            \item Atrybut \texttt{serviceId} w kolekcji \texttt{serviceOrders} zawiera referencję do identyfikatora dokumentu z kolekcji \texttt{services}
            \item Modeluje relację: "Zamówienie dotyczy konkretnej usługi" (jedna usługa może być zamawiana wielokrotnie)
        \end{itemize}
    \end{enumerate}


    \section{Zapytania}

    \subsection{Zapytania wyszukujące (find)}

    \subsubsection{Dostępne pokoje o pojemności większej niż 2 osoby}

    \begin{minted}{javascript}
// Zapytanie wyszukujące dostępne pokoje o pojemności większej niż 2 osoby
db.rooms.find(
  {
    status: "Dostępny",
    capacity: { $gt: 2 }
  }
)
    \end{minted}

    Zapytanie zwraca wszystkie pokoje, które są obecnie dostępne i mogą pomieścić więcej niż 2 osoby.
    Wykorzystuje operator porównujący \texttt{\$gt} (greater than).

    \subsubsection{Rezerwacje rozpoczynające się w określonym przedziale czasowym}

    \begin{minted}{javascript}
// Zapytanie wyszukujące rezerwacje z zameldowaniem w czerwcu 2023
db.reservations.find(
  {
    checkInDate: {
      $gte: new Date("2023-06-01"),
      $lt: new Date("2023-07-01")
    }
  }
)
    \end{minted}

    Zapytanie zwraca wszystkie rezerwacje z datą zameldowania w czerwcu 2023.
    Wykorzystuje operatory porównujące \texttt{\$gte} (greater than or equal) i \texttt{\$lt} (less than).

    \subsection{Zapytania grupujące (aggregate)}

    \subsubsection{Średnia cena i liczba rezerwacji według typu pokoju}

    \begin{minted}{javascript}
// Zapytanie grupujące - statystyki rezerwacji wg typu pokoju
db.reservations.aggregate([
  {
    $lookup: {
      from: "rooms",
      localField: "roomId",
      foreignField: "_id",
      as: "room"
    }
  },
  {
    $unwind: "$room"
  },
  {
    $group: {
      _id: "$room.type",
      averagePrice: { $avg: "$totalPrice" },
      totalReservations: { $sum: 1 },
      totalRevenue: { $sum: "$totalPrice" }
    }
  },
  {
    $sort: {
      totalRevenue: -1
    }
  },
  {
    $project: {
      roomType: "$_id",
      averagePrice: { $round: ["$averagePrice", 2] },
      totalReservations: 1,
      totalRevenue: 1,
      _id: 0
    }
  }
])
    \end{minted}

    Zapytanie łączy dane z kolekcji rezerwacji i pokoi, a następnie grupuje je według typu pokoju.
    Dla każdego typu pokoju obliczane są: średnia cena rezerwacji, liczba rezerwacji i całkowity przychód.
    Wyniki są sortowane według przychodu malejąco.
    Wykorzystane operatory to \texttt{\$group}, \texttt{\$lookup}, \texttt{\$sort} i \texttt{\$project}.

    \subsubsection{Analiza zamówień usług dodatkowych według kategorii}

    \begin{minted}{javascript}
// Zapytanie grupujące - analiza zamówień usług wg kategorii
db.serviceOrders.aggregate([
  {
    $lookup: {
      from: "services",
      localField: "serviceId",
      foreignField: "_id",
      as: "serviceDetails"
    }
  },
  {
    $unwind: "$serviceDetails"
  },
  {
    $match: {
      status: { $in: ["Potwierdzone", "Zrealizowane"] }
    }
  },
  {
    $group: {
      _id: "$serviceDetails.category",
      totalOrders: { $sum: 1 },
      totalRevenue: { $sum: "$totalPrice" },
      averageQuantity: { $avg: "$quantity" }
    }
  },
  {
    $sort: {
      totalOrders: -1
    }
  },
  {
    $limit: 5
  },
  {
    $project: {
      category: "$_id",
      totalOrders: 1,
      totalRevenue: { $round: ["$totalRevenue", 2] },
      averageQuantity: { $round: ["$averageQuantity", 2] },
      _id: 0
    }
  }
])
    \end{minted}

    Zapytanie analizuje zamówienia usług dodatkowych, łącząc dane z kolekcji zamówień i usług.
    Filtruje zamówienia o statusie "Potwierdzone" lub "Zrealizowane", grupuje je według kategorii usługi i oblicza statystyki: liczbę zamówień, całkowity przychód i średnią ilość zamówionych usług.
    Wyniki są sortowane według liczby zamówień i ograniczone do 5 najlepszych kategorii.
    Wykorzystane operatory to \texttt{\$lookup}, \texttt{\$match}, \texttt{\$group}, \texttt{\$sort}, \texttt{\$limit} i \texttt{\$project}.

    \subsection{Zapytanie zliczające (count)}

    \begin{minted}{javascript}
// Zapytanie zliczające pokoje wg statusu dostępności
db.rooms.countDocuments(
  {
    status: "Dostępny",
    pricePerNight: { $lt: 500 }
  }
)
    \end{minted}

    Zapytanie zwraca liczbę pokoi, które są obecnie dostępne i kosztują mniej niż 500 zł za noc.
    Wykorzystuje metodę \texttt{countDocuments} z parametrem query.

    \subsection{Zapytanie o wartości unikalne (distinct)}

    \begin{minted}{javascript}
// Zapytanie o unikalne kraje pochodzenia gości
db.guests.distinct(
  "address.country",
  {
    loyaltyPoints: { $gt: 50 }
  }
)
    \end{minted}

    Zapytanie zwraca listę unikalnych krajów pochodzenia gości, którzy posiadają więcej niż 50 punktów lojalnościowych.
    Wykorzystuje metodę \texttt{distinct} z parametrem query.


    \section{Indeksy}

    W celu optymalizacji zapytań w bazie danych utworzono następujące indeksy:

    \begin{minted}{javascript}
// Indeks dla szybkiego wyszukiwania pokoi po numerze
db.rooms.createIndex({ roomNumber: 1 }, { unique: true })

// Indeks dla szybkiego wyszukiwania gości po nazwisku i imieniu
db.guests.createIndex({ lastName: 1, firstName: 1 })

// Indeks dla szybkiego wyszukiwania rezerwacji wg dat
db.reservations.createIndex({ checkInDate: 1, checkOutDate: 1 })

// Indeks dla szybszego łączenia rezerwacji z pokojami
db.reservations.createIndex({ roomId: 1 })

// Indeks dla szybszego łączenia rezerwacji z gośćmi
db.reservations.createIndex({ guestId: 1 })

// Indeks dla szybkiego wyszukiwania usług wg kategorii i ceny
db.services.createIndex({ category: 1, price: 1 })

// Indeks dla szybszego łączenia zamówień usług z usługami
db.serviceOrders.createIndex({ serviceId: 1 })
    \end{minted}

    Indeksy przyspieszają operacje wyszukiwania i łączenia danych, szczególnie w przypadku złożonych zapytań agregujących.
    Na przykład, indeks \texttt{roomNumber} zapewnia szybkie wyszukiwanie pokoju po jego numerze, a indeksy na polach \texttt{guestId} i \texttt{roomId} w kolekcji \texttt{reservations} przyspieszają operacje łączenia danych z różnych kolekcji.

\end{document}
