diff --git a/README.md b/README.md
index dbcd01351cca650ec888ee561b73741453b83755..64347809c2e2a37f909bd2ae85a68c13588331fc 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,9 @@ airline-ticket-sales-service/   # Корневая директория прое
 ├── main.py                     # Основной файл программы, "точка входа"
 в”њв”Ђв”Ђ models/                     
 │   ├── flight.py               # Класс для управления рейсами
-в”‚   в”њв”Ђв”Ђ __init__.py            
+в”‚   в”њв”Ђв”Ђ __init__.py  
+в”‚   в”њв”Ђв”Ђ flight_types.py 
+в”‚   в”њв”Ђв”Ђ exceptions.py        
 ├── pyproject.toml              # Зависимости проекта
 в”њв”Ђв”Ђ requirements.txt
 в”њв”Ђв”Ђ .gitignore
@@ -83,6 +85,44 @@ airline-ticket-sales-service/   # Корневая директория прое
 3. Установить время вылета
 4. Установить время прибытия 
 5. Завершить заполнение
+
+**Вопрос:** Как работает класс InternationalFlight?
+
+Класс InternationalFlight используется для управления международными рейсами. Он позволяет:
+
+- устанавливать и получать информацию о необходимости визы (visa_required).
+
+- Получать информацию обо всех созданных международных рейсах через метод get_all_instances.
+
+**Вопрос:** Как работает класс CharterFlight?
+
+Класс CharterFlight предназначен для управления чартерными рейсами. Он позволяет:
+
+- устанавливать и получать информацию об операторе рейса (operator).
+
+- получать информацию обо всех созданных чартерных рейсах через метод get_all_instances.
+
+**Вопрос:** Как работает класс DomesticFlight?
+
+Класс DomesticFlight используется для управления внутренними рейсами. Он позволяет:
+
+- устанавливать и получать информацию о том, является ли рейс лоукостом (is_low_cost).
+
+- получать информацию обо всех созданных внутренних рейсах через метод get_all_instances.
+
+**Вопрос:** Как получить информацию обо всех рейсах?
+
+- Для каждого типа рейса (международные, чартерные, внутренние) используйте соответствующий статический метод:
+
+**InternationalFlight.get_all_instances()**
+
+**CharterFlight.get_all_instances()**
+
+**DomesticFlight.get_all_instances()**
+
+**Вопрос:** Что делать, если возникает ошибка при установке данных?
+
+- Если возникает ошибка (например, ValueError), проверьте вводимые данные.
 ## To do
 
 - [ ] Реализовать удобный интерфейс 
diff --git a/models/flight.py b/models/flight.py
index d1f46cfe5ac63a6220aecdbaf2b74457579ad154..2cd6574478d0b6d2e2bc3fca6e65b9830963136c 100644
--- a/models/flight.py
+++ b/models/flight.py
@@ -1,154 +1,180 @@
+from typing import TypeVar, Generic
 from datetime import datetime
 
 
-class Flight:
-    def __init__(self):
-        """
-        Инициализирует объект Flight с начальными значениями.
-        """
-        self._flight_number: str | None = None
-        self._departure: str | None = None
-        self._destination: str | None = None
-        self._departure_time: str | None = None
-        self._arrival_time: str | None = None
+class LoggingMixin:
+    """Миксин для логирования действий."""
 
-    def get_flight_number(self) -> str | None:
+    def log_action(self, action: str) -> None:
         """
-        Возвращает номер рейса.
+        Логирует действие с указанием класса, в котором оно произошло.
 
-        Возвращает:
-            str | None: Номер рейса, если он установлен, иначе None.
+        :param action: Действие, которое нужно залогировать.
         """
-        return self._flight_number
+        print(f"[LOG] {action} - {self.__class__.__name__}")
 
-    def set_flight_number(self, flight_number: str) -> None:
-        """
-        Устанавливает номер рейса.
+class IDMixin:
+    """Миксин для генерации уникальных идентификаторов."""
 
-        Аргументы:
-            flight_number (str): Номер рейса. Должен быть непустой строкой.
-
-        Вызывает:
-            ValueError: Если номер рейса не является непустой строкой.
-        """
-        if isinstance(flight_number, str) and flight_number.strip():
-            self._flight_number = flight_number
-        else:
-            raise ValueError("Flight number must be a non-empty string")
+    _id_counter: int = 0 
 
-    def get_departure(self) -> str | None:
+    def generate_unique_id(self) -> int:
         """
-        Возвращает пункт отправления.
+        Генерирует уникальный идентификатор.
 
-        Возвращает:
-            str | None: Пункт отправления, если он установлен, иначе None.
+        :return: Уникальный целочисленный идентификатор.
         """
-        return self._departure
+        IDMixin._id_counter += 1
+        return IDMixin._id_counter
 
-    def set_departure(self, departure: str) -> None:
-        """
-        Устанавливает пункт отправления.
+class FlightMeta(type):
+    """Метакласс для автоматической регистрации всех классов рейсов."""
 
-        Аргументы:
-            departure (str): Пункт отправления. Должен быть непустой строкой.
+    registered_flights: list = []  
 
-        Вызывает:
-            ValueError: Если пункт отправления не является непустой строкой.
+    def __new__(cls, name: str, bases: tuple, dct: dict) -> type:
         """
-        if isinstance(departure, str) and departure.strip():
-            self._departure = departure
-        else:
-            raise ValueError("The departure point must be a non-empty string")
+        Создает новый класс и регистрирует его, если это не базовый класс Flight.
 
-    def get_destination(self) -> str | None:
+        :param name: Имя класса.
+        :param bases: Кортеж базовых классов.
+        :param dct: Словарь атрибутов класса.
+        :return: Новый класс.
         """
-        Возвращает пункт назначения.
+        new_class = super().__new__(cls, name, bases, dct)
+        if name != "Flight":  
+            cls.registered_flights.append(new_class)
+        return new_class
 
-        Возвращает:
-            str | None: Пункт назначения, если он установлен, иначе None.
-        """
-        return self._destination
+FlightNumber = TypeVar("FlightNumber") 
 
-    def set_destination(self, destination: str) -> None:
-        """
-        Устанавливает пункт назначения.
+class Flight(LoggingMixin, IDMixin, Generic[FlightNumber], metaclass=FlightMeta):
+    """Базовый класс для представления рейса."""
 
-        Аргументы:
-            destination (str): Пункт назначения. Должен быть непустой строкой.
+    __slots__ = [
+        "_flight_number",
+        "_departure",
+        "_destination",
+        "_departure_time",
+        "_arrival_time",
+        "_available_seats",
+        "_flight_id",
+    ]
 
-        Вызывает:
-            ValueError: Если пункт назначения не является непустой строкой.
-        """
-        if isinstance(destination, str) and destination.strip():
-            self._destination = destination
+    def __init__(self) -> None:
+        """Инициализирует объект рейса."""
+        super().__init__()
+        self._flight_number: FlightNumber | None = None 
+        self._departure: str | None = None 
+        self._destination: str | None = None 
+        self._departure_time: str | None = None 
+        self._arrival_time: str | None = None 
+        self._available_seats: int = 0
+        self._flight_id: int = self.generate_unique_id() 
+        self.log_action("Flight created") 
+
+    @property
+    def flight_number(self) -> FlightNumber | None:
+        """Возвращает номер рейса."""
+        return self._flight_number
+
+    @flight_number.setter
+    def flight_number(self, value: FlightNumber) -> None:
+        """Устанавливает номер рейса."""
+        if isinstance(value, str) and value.strip():
+            self._flight_number = value
+            self.log_action(f"Flight number set to {value}")
         else:
-            raise ValueError("Destination must be a non-empty string")
+            raise ValueError("Flight number must be a non-empty string")
 
-    def get_departure_time(self) -> str | None:
-        """
-        Возвращает время вылета.
+    @property
+    def departure(self) -> str | None:
+        """Возвращает пункт отправления."""
+        return self._departure
 
-        Возвращает:
-            str | None: Время вылета, если оно установлено, иначе None.
-        """
-        return self._departure_time
+    @departure.setter
+    def departure(self, value: str) -> None:
+        """Устанавливает пункт отправления."""
+        if isinstance(value, str) and value.strip():
+            self._departure = value
+            self.log_action(f"Departure set to {value}")
+        else:
+            raise ValueError("The departure point must be a non-empty string")
 
-    def set_departure_time(self, departure_time: str) -> None:
-        """
-        Устанавливает время вылета.
+    @property
+    def destination(self) -> str | None:
+        """Возвращает пункт назначения."""
+        return self._destination
 
-        Аргументы:
-            departure_time (str): Время вылета. Должно быть строкой в формате ISO.
+    @destination.setter
+    def destination(self, value: str) -> None:
+        """Устанавливает пункт назначения."""
+        if isinstance(value, str) and value.strip():
+            self._destination = value
+            self.log_action(f"Destination set to {value}")
+        else:
+            raise ValueError("Destination must be a non-empty string")
 
-        Вызывает:
-            ValueError: Если время вылета некорректно или позже времени прибытия.
-        """
-        if self._is_valid_time(departure_time) and (
-            self._arrival_time is None or self._arrival_time > departure_time
+    @property
+    def departure_time(self) -> str | None:
+        """Возвращает время отправления."""
+        return self._departure_time
+
+    @departure_time.setter
+    def departure_time(self, value: str) -> None:
+        """Устанавливает время отправления."""
+        if self._is_valid_time(value) and (
+            self._arrival_time is None or value < self._arrival_time
         ):
-            self._departure_time = departure_time
+            self._departure_time = value
+            self.log_action(f"Departure time set to {value}")
         else:
             raise ValueError(
                 "Incorrect departure time or it is later than arrival time"
             )
 
-    def get_arrival_time(self) -> str | None:
-        """
-        Возвращает время прибытия.
-
-        Возвращает:
-            str | None: Время прибытия, если оно установлено, иначе None.
-        """
+    @property
+    def arrival_time(self) -> str | None:
+        """Возвращает время прибытия."""
         return self._arrival_time
 
-    def set_arrival_time(self, arrival_time: str) -> None:
-        """
-        Устанавливает время прибытия.
-
-        Аргументы:
-            arrival_time (str): Время прибытия. Должно быть строкой в формате ISO.
-
-        Вызывает:
-            ValueError: Если время прибытия некорректно или раньше времени вылета.
-        """
-        if self._is_valid_time(arrival_time) and (
-            self._departure_time is None or arrival_time > self._departure_time
+    @arrival_time.setter
+    def arrival_time(self, value: str) -> None:
+        """Устанавливает время прибытия."""
+        if self._is_valid_time(value) and (
+            self._departure_time is None or value > self._departure_time
         ):
-            self._arrival_time = arrival_time
+            self._arrival_time = value
+            self.log_action(f"Arrival time set to {value}")
         else:
             raise ValueError(
                 "Incorrect arrival time or it is earlier than departure time"
             )
 
+    @property
+    def available_seats(self) -> int:
+        """Возвращает количество свободных мест."""
+        return self._available_seats
+
+    @available_seats.setter
+    def available_seats(self, value: int) -> None:
+        """Устанавливает количество свободных мест."""
+        if value < 0:
+            raise ValueError("Available seats cannot be negative")
+        self._available_seats = value
+        self.log_action(f"Available seats set to {value}")
+
+    @property
+    def flight_id(self) -> int:
+        """Возвращает уникальный ID рейса."""
+        return self._flight_id
+
     def _is_valid_time(self, time_str: str) -> bool:
         """
         Проверяет, является ли строка времени корректной в формате ISO.
 
-        Аргументы:
-            time_str (str): Строка времени для проверки.
-
-        Возвращает:
-            bool: True, если строка времени корректна, иначе False.
+        :param time_str: Строка времени для проверки.
+        :return: True, если строка времени корректна, иначе False.
         """
         try:
             datetime.fromisoformat(time_str)
@@ -156,12 +182,11 @@ class Flight:
         except ValueError:
             return False
 
-    def get_flight_info(self) -> dict[str, str | None]:
+    def get_flight_info(self) -> dict:
         """
         Возвращает информацию о рейсе в виде словаря.
 
-        Возвращает:
-            dict[str, str | None]: Словарь, содержащий информацию о рейсе.
+        :return: Словарь с информацией о рейсе.
         """
         return {
             "flight_number": self._flight_number,
@@ -169,4 +194,23 @@ class Flight:
             "destination": self._destination,
             "departure_time": self._departure_time,
             "arrival_time": self._arrival_time,
+            "available_seats": self._available_seats,
         }
+
+
+class FlightAvailability:
+    """Класс для проверки доступности рейса."""
+
+    @staticmethod
+    def check_availability(flight: Flight) -> bool:
+        """
+        Проверяет, доступен ли рейс для бронирования.
+
+        :param flight: Рейс для проверки.
+        :return: True, если рейс доступен, иначе False.
+        """
+        if not flight.flight_number:
+            return False
+        if flight.available_seats == 0:  
+            return False
+        return True
diff --git a/models/flight_types.py b/models/flight_types.py
index 0dece7299a60ba9d53c23f79907a2f5bf83de460..fccf71f316b65096524c81dc45545ec3879bf3ae 100644
--- a/models/flight_types.py
+++ b/models/flight_types.py
@@ -1,184 +1,94 @@
-from models.flight import Flight
+from models.flight import Flight, FlightNumber
 
 
-class InternationalFlight(Flight):
-    __instances = []
+class InternationalFlight(Flight[FlightNumber]):
+    __slots__ = ["_visa_required"]
+    _instances = []
 
     def __init__(self):
-        """
-        Инициализирует объект InternationalFlight.
-        """
         super().__init__()
-        self.__visa_required: bool | None = None
-        InternationalFlight.__instances.append(self)
-
-    def get_visa_required(self) -> bool | None:
-        """
-        Возвращает информацию о необходимости визы.
-
-        Returns:
-            bool | None: True, если виза требуется, иначе False или None.
-        """
-        return self.__visa_required
-
-    def set_visa_required(self, visa_required: bool) -> None:
-        """
-        Устанавливает необходимость визы.
-
-        Args:
-            visa_required (bool): True, если виза требуется, иначе False.
-
-        Raises:
-            ValueError: Если значение не является булевым.
-        """
-        if isinstance(visa_required, bool):
-            self.__visa_required = visa_required
-        else:
-            raise ValueError("Visa required must be a boolean")
+        self._visa_required: bool | None = None
+        InternationalFlight._instances.append(self)
 
-    def get_flight_info(self) -> dict[str, str | bool | None]:
-        """
-        Возвращает информацию о рейсе.
+    @property
+    def visa_required(self) -> bool | None:
+        """Возвращает, требуется ли виза для международного рейса."""
+        return self._visa_required
 
-        Returns:
-            dict[str, str | bool | None]: Словарь с информацией о рейсе.
-        """
-        base_info = super().get_flight_info()
-        base_info["visa_required"] = self.__visa_required
-        return base_info
+    @visa_required.setter
+    def visa_required(self, value: bool) -> None:
+        """Устанавливает, требуется ли виза для международного рейса."""
+        self._visa_required = value
+        self.log_action(f"Visa required set to {value}")
 
-    @staticmethod
-    def get_all_instances() -> list[tuple[dict[str, str | bool | None], str]]:
+    def get_flight_info(self) -> dict:
         """
-        Возвращает список всех созданных объектов InternationalFlight с их информацией.
+        Возвращает информацию о международном рейсе.
 
-        Returns:
-            list[tuple[dict[str, str | bool | None], str]]:
-            Список кортежей с информацией о рейсе и его типе.
+        :return: Словарь с информацией о рейсе, включая необходимость визы.
         """
-        return [
-            (flight.get_flight_info(), "International")
-            for flight in InternationalFlight.__instances
-        ]
+        info = super().get_flight_info()
+        info["visa_required"] = self._visa_required
+        return info
 
-
-class CharterFlight(Flight):
-    __instances = []
+class CharterFlight(Flight[FlightNumber]):
+    __slots__ = ["_operator"]
+    _instances = []
 
     def __init__(self):
-        """
-        Инициализирует объект CharterFlight.
-        """
         super().__init__()
-        self.__operator: str | None = None
-        CharterFlight.__instances.append(self)
+        self._operator: str | None = None
+        CharterFlight._instances.append(self)
 
-    def get_operator(self) -> str | None:
-        """
-        Возвращает оператора чартерного рейса.
+    @property
+    def operator(self) -> str | None:
+        """Возвращает оператора чартерного рейса."""
+        return self._operator
 
-        Returns:
-            str | None: Название оператора или None.
-        """
-        return self.__operator
+    @operator.setter
+    def operator(self, value: str) -> None:
+        """Устанавливает оператора чартерного рейса."""
+        self._operator = value
+        self.log_action(f"Operator set to {value}")
 
-    def set_operator(self, operator: str) -> None:
+    def get_flight_info(self) -> dict:
         """
-        Устанавливает оператора чартерного рейса.
+        Возвращает информацию о чартерном рейсе.
 
-        Args:
-            operator (str): Название оператора.
-
-        Raises:
-            ValueError: Если название оператора не является непустой строкой.
+        :return: Словарь с информацией о рейсе, включая оператора.
         """
-        if isinstance(operator, str) and operator.strip():
-            self.__operator = operator
-        else:
-            raise ValueError("Operator must be a non-empty string")
+        info = super().get_flight_info()
+        info["operator"] = self._operator
+        return info
 
-    def get_flight_info(self) -> dict[str, str | None]:
-        """
-        Возвращает информацию о рейсе.
 
-        Returns:
-            dict[str, str | None]: Словарь с информацией о рейсе.
-        """
-        base_info = super().get_flight_info()
-        base_info["operator"] = self.__operator
-        return base_info
-
-    @staticmethod
-    def get_all_instances() -> list[tuple[dict[str, str | None], str]]:
-        """
-        Возвращает список всех созданных объектов CharterFlight с их информацией.
-
-        Returns:
-            list[tuple[dict[str, str | None], str]]:
-            Список кортежей с информацией о рейсе и его типе.
-        """
-        return [
-            (flight.get_flight_info(), "Charter")
-            for flight in CharterFlight.__instances
-        ]
+class DomesticFlight(Flight[FlightNumber]): 
+    __slots__ = ["_is_low_cost"]
+    _instances = []
 
 
-class DomesticFlight(Flight):
-    __instances = []
-
     def __init__(self):
-        """
-        Инициализирует объект DomesticFlight.
-        """
         super().__init__()
-        self.__is_low_cost: bool | None = None
-        DomesticFlight.__instances.append(self)
+        self._is_low_cost: bool | None = None
+        DomesticFlight._instances.append(self)
 
-    def get_is_low_cost(self) -> bool | None:
-        """
-        Возвращает информацию о том, является ли рейс лоукост.
+    @property
+    def is_low_cost(self) -> bool | None:
+        """Возвращает, является ли рейс низкобюджетным."""
+        return self._is_low_cost
 
-        Returns:
-            bool | None: True, если рейс лоукост, иначе False или None.
-        """
-        return self.__is_low_cost
-
-    def set_is_low_cost(self, is_low_cost: bool) -> None:
-        """
-        Устанавливает, является ли рейс лоукост.
-
-        Args:
-            is_low_cost (bool): True, если рейс лоукост, иначе False.
-
-        Raises:
-            ValueError: Если значение не является булевым.
-        """
-        if isinstance(is_low_cost, bool):
-            self.__is_low_cost = is_low_cost
-        else:
-            raise ValueError("Is low cost must be a boolean")
-
-    def get_flight_info(self) -> dict[str, str | bool | None]:
-        """
-        Возвращает информацию о рейсе.
-
-        Returns:
-            dict[str, str | bool | None]: Словарь с информацией о рейсе.
-        """
-        base_info = super().get_flight_info()
-        base_info["is_low_cost"] = self.__is_low_cost
-        return base_info
+    @is_low_cost.setter
+    def is_low_cost(self, value: bool) -> None:
+        """Устанавливает, является ли рейс низкобюджетным."""
+        self._is_low_cost = value
+        self.log_action(f"Is low cost set to {value}")
 
-    @staticmethod
-    def get_all_instances() -> list[tuple[dict[str, str | bool | None], str]]:
+    def get_flight_info(self) -> dict:
         """
-        Возвращает список всех созданных объектов DomesticFlight с их информацией.
+        Возвращает информацию о внутреннем рейсе.
 
-        Returns:
-            list[tuple[dict[str, str | bool | None], str]]:
-            Список кортежей с информацией о рейсе и его типе.
+        :return: Словарь с информацией о рейсе, включая флаг низкобюджетности.
         """
-        return [
-            (flight.get_flight_info(), "Domestic")
-            for flight in DomesticFlight.__instances
-        ]
+        info = super().get_flight_info()
+        info["is_low_cost"] = self._is_low_cost
+        return info