
- •Введение
- •Анализ предметной области
- •Диаграммы прецедентов
- •Диаграммы взаимодействия
- •Диаграммы поведения
- •Проектирование бд с использованием case-средств
- •Создание сайта с использованием ms Visual Studio Разметка и наполнение сайта
- •Реализация личного кабинета пользователя
- •Фильтрация данных
- •Администрирование базы данных
- •Заключение
- •Список использованной литературы
- •Приложение а
- •Приложение б
- •Приложение в
- •Приложение г
- •Приложение д
- •Приложение е
- •Приложение ж
- •Приложение з
- •Приложение и
Фильтрация данных
Разработана страница поиска туров с фильтрацией по типу тура, стране, по типу и стране (Рисунок 25-27).
Рисунок 25- Разметка страницы Поиск туров
Рисунок 26- Настройка источника данных для GridView
Листинг 5- Функции для обработки нажатий на кнопки
protected void Button1_Click(object sender, EventArgs e)
{
string type = DropDownList1.SelectedValue;
SqlDataSource1.SelectCommand = GetSqlCommand(type, null);
GridView1.DataBind();
}
protected void Button2_Click(object sender, EventArgs e)
{
string country = DropDownList2.SelectedValue;
SqlDataSource1.SelectCommand = GetSqlCommand(null, country);
GridView1.DataBind();
}
protected void Button3_Click(object sender, EventArgs e)
{
string type = DropDownList1.SelectedValue;
string country = DropDownList2.SelectedValue;
SqlDataSource1.SelectCommand = GetSqlCommand(type, country);
GridView1.DataBind();
}
Листинг 6- Генерация SQL-запрос для фильтрации туров на основе типа и страны
private string GetSqlCommand(string type, string country)
{
string sql = @"SELECT
Tour.Tour_ID AS 'TourID',
Tour.Name_T AS 'Tour Name',
Tour.Description_T AS 'Description',
Tour.Duration_T AS 'Duration',
Type_T.Name_T AS 'Tour Type',
Season.Name_Season AS 'Season',
Hotel.Name_H AS 'Hotel Name',
Locality.Name_L AS 'Route Locality',
Locality.Country AS 'Country',
Image.FilePath AS 'Image Path'
FROM
Tour
JOIN
Type_T ON Tour.TypeT_ID = Type_T.TypeT_ID
JOIN
TourSeason ON Tour.Tour_ID = TourSeason.Tour_ID
JOIN
Season ON TourSeason.Season_ID = Season.Season_ID
JOIN
TourHotel ON Tour.Tour_ID = TourHotel.Tour_ID
JOIN
Hotel ON TourHotel.Hotel_ID = Hotel.Hotel_ID
JOIN
Route ON Tour.Tour_ID = Route.Tour_ID
JOIN
Locality ON Route.Locality_ID = Locality.Locality_ID
LEFT JOIN
ImageTour ON Tour.Tour_ID = ImageTour.TourID
LEFT JOIN
Image ON ImageTour.ImageID = Image.ImageID";
SqlDataSource1.SelectParameters.Clear();
if (!string.IsNullOrEmpty(type) && !string.IsNullOrEmpty(country))
{
sql += " WHERE Type_T.Name_T = @Type AND Locality.Country = @Country";
SqlDataSource1.SelectParameters.Add(new Parameter("Type", DbType.String, type));
SqlDataSource1.SelectParameters.Add(new Parameter("Country", DbType.String, country));
}
else if (!string.IsNullOrEmpty(type))
{
sql += " WHERE Type_T.Name_T = @Type";
SqlDataSource1.SelectParameters.Add(new Parameter("Type", DbType.String, type));
}
else if (!string.IsNullOrEmpty(country))
{
sql += " WHERE Locality.Country = @Country";
SqlDataSource1.SelectParameters.Add(new Parameter("Country", DbType.String, country));
}
return sql;
}
Рисунок 27- Страница Поиск туров
На рисунках 28-29 показана работа фильтрации.
Рисунок 28- Применение фильтрации по типу тура
Рисунок 29- Применение фильтрации по типу и стране
При нажатии на Выбор пользователь может открыть страницу тура для просмотра более подробной информации о туре. Написана функция GridView1_SelectedIndexChanged, которая получает идентификатор выбранного тура и перенаправляет пользователя на страницу с подробной информацией, передавая идентификатор в качестве параметра в URL.
Листинг 7- Функция обработки нажатия кнопки для просмотра подробной информации о туре
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
int selectedTourID = Convert.ToInt32(GridView1.SelectedDataKey.Value);
Response.Redirect($"TourDetails.aspx?TourID={selectedTourID}");
Листинг 8- Функция отображения подробной информации о туре
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string tourID = Request.QueryString["TourID"];
if (!string.IsNullOrEmpty(tourID))
{
DataTable tourDetails = GetTourDetails(tourID);
if (tourDetails.Rows.Count > 0)
{
DataRow row = tourDetails.Rows[0];
TourNameLabel.Text = row["TourName"].ToString();
DescriptionLabel.Text = row["Description"].ToString();
DurationLabel.Text = row["Duration"].ToString();
SeasonLabel.Text = row["Season"].ToString();
HotelNameLabel.Text = row["HotelName"].ToString();
LocalityLabel.Text = row["Locality"].ToString();
CountryLabel.Text = row["Country"].ToString();
string imagePath = row["ImagePath"].ToString();
}
}
}
Далее создана возможность оформления заказа пользователем. На странице тура есть возможно выбора дат для путешествия и проверки количества доступных путевок (Рисунок 30). При выборе дат и количества путевок пользователь получает сообщение о доступности или отсутствии путевок (Рисунок 31-32).
Рисунок 30- Страница тура и выбора дат
Рисунок 31 - Получение сообщения о доступности поездки
Рисунок 32- Сообщение о недоступности мест
Листинг 9- Функция для проверки доступности мест для бронирования на выбранную дату
protected void CheckAvailabilityButton_Click(object sender, EventArgs e)
{
string tourID = Request.QueryString["TourID"];
string startDate = StartDateTextBox.Text;
if (!int.TryParse(TicketCountTextBox.Text, out int ticketsRequested) || ticketsRequested <= 0)
{
AvailabilityLabel.Text = "Введите корректное количество путевок.";
AvailabilityLabel.CssClass = "error";
OrderButton.Visible = false;
return;
}
string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["travelConnectionString4"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connectionString))
{
string query = @"SELECT TripCount FROM Trip WHERE Tour_ID = @TourID AND StartDate = @StartDate";
using (SqlCommand cmd = new SqlCommand(query, conn))
{
cmd.Parameters.AddWithValue("@TourID", tourID);
cmd.Parameters.AddWithValue("@StartDate", startDate);
conn.Open();
object result = cmd.ExecuteScalar();
if (result != null && int.TryParse(result.ToString(), out int availableTickets))
{
if (availableTickets >= ticketsRequested)
{
AvailabilityLabel.Text = "Достаточно мест для бронирования.";
AvailabilityLabel.CssClass = "success";
OrderButton.Visible = true;
}
else
{
AvailabilityLabel.Text = "Недостаточно мест для бронирования.";
AvailabilityLabel.CssClass = "error";
OrderButton.Visible = false;
}
}
else
{
AvailabilityLabel.Text = "Нет данных для выбранной даты.";
AvailabilityLabel.CssClass = "error";
OrderButton.Visible = false;
}
}
}
}
При нажатии на кнопку «Перейти к оформлению заказа» открывается форма для заполнения данных пассажиров (Рисунок 33). В зависимости от количества путевок создаются текстовые поля и метки для ввода информации о пассажирах. Также рассчитывается общая стоимость тура, умножая цену одной путевки на количество путевок (Листинг 10).
Рисунок 33- Подробная информация о туре
Листинг 10- Функция расчета стоимости
private void CalculateTotalPrice(string tourID, int ticketsCount)
{
string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["travelConnectionString4"].ConnectionString;
try
{
using (SqlConnection conn = new SqlConnection(connectionString))
{ string query = @"SELECT Price FROM Trip WHERE Tour_ID = @TourID AND StartDate = @StartDate";
using (SqlCommand cmd = new SqlCommand(query, conn))
{
cmd.Parameters.AddWithValue("@TourID", tourID);
cmd.Parameters.AddWithValue("@StartDate", DateTime.Parse(StartDateLabel.Text));
conn.Open();
object result = cmd.ExecuteScalar();
if (result != null)
{
decimal pricePerTicket = Convert.ToDecimal(result);
decimal totalPrice = pricePerTicket * ticketsCount;
TotalPriceLabel.Text = $"Общая стоимость: {totalPrice:C}"; // Выводим стоимость
}
else
{
ErrorMessage.Text = "Ошибка: Цена не найдена.";
}
}
}
}
catch (Exception ex)
{
ErrorMessage.Text = $"Ошибка расчета стоимости: {ex.Message}";
}
}
При правильно заполненных данных, создается запись в таблице Заказ (Листинг 11), а в таблицу с путевками заносятся данные о пассажирах, которые привязаны к путевке (Листинг 12). Также при оформлении заказа, уменьшается количество доступных путевок (Листинг 13) (Рисунок 34-37).
Рисунок 34- Таблица с доступными путевками до оформления заказа
Рисунок 35- Успешное оформление заказа
Рисунок 36- Таблица с доступными путевками после оформления заказа
Рисунок
37- Таблицами с путевками
Листинг 11- Функция для создания записи в таблице с заказами
private int InsertOrder(SqlConnection conn, SqlTransaction transaction, int tripID, int ticketsCount)
{
string query = @"
INSERT INTO Order_data (OrderDate, Client_ID, PeopleCount, Trip_ID)
OUTPUT INSERTED.Order_ID
VALUES (GETDATE(), @ClientID, @PeopleCount, @TripID)";
using (SqlCommand cmd = new SqlCommand(query, conn, transaction))
{
cmd.Parameters.AddWithValue("@ClientID", Session["UserId"]);
cmd.Parameters.AddWithValue("@PeopleCount", ticketsCount);
cmd.Parameters.AddWithValue("@TripID", tripID);
return (int)cmd.ExecuteScalar();
}
}
Листинг 12 – Добавление оформленных путевок в таблицу с путевками
private void AddPassengers(SqlConnection conn, SqlTransaction transaction, int orderID, int ticketsCount)
{
string query = @"
INSERT INTO Permit (Order_ID, LastName, FirstName, MiddleName, DOB)
VALUES (@OrderID, @LastName, @FirstName, @MiddleName, @DOB)";
for (int i = 1; i <= ticketsCount; i++)
{
string passengerName = ((TextBox)PassengersPanel.FindControl($"PassengerName_{i}"))?.Text;
string passengerDOB = ((TextBox)PassengersPanel.FindControl($"PassengerDOB_{i}"))?.Text;
string[] nameParts = passengerName?.Split(' ');
if (nameParts == null || nameParts.Length < 2)
{
throw new Exception($"Ошибка в данных пассажира {i}. Укажите ФИО в формате: 'Фамилия Имя Отчество'.");
}
string lastName = nameParts[0];
string firstName = nameParts[1];
string middleName = nameParts.Length > 2 ? nameParts[2] : "";
if (string.IsNullOrEmpty(passengerDOB) || !DateTime.TryParse(passengerDOB, out DateTime dob))
{
throw new Exception($"Ошибка в данных пассажира {i}. Укажите корректную дату рождения.");
}
using (SqlCommand cmd = new SqlCommand(query, conn, transaction))
{
cmd.Parameters.AddWithValue("@OrderID", orderID);
cmd.Parameters.AddWithValue("@LastName", lastName);
cmd.Parameters.AddWithValue("@FirstName", firstName);
cmd.Parameters.AddWithValue("@MiddleName", middleName);
cmd.Parameters.AddWithValue("@DOB", dob);
cmd.ExecuteNonQuery();
}
}
}
Листинг 13- Функция уменьшения количества доступных путевок
private void UpdateTripCount(SqlConnection conn, SqlTransaction transaction, int tripID, int ticketsCount)
{
string query = @"
UPDATE Trip
SET TripCount = TripCount - @TicketsCount
WHERE Trip_ID = @TripID";
using (SqlCommand cmd = new SqlCommand(query, conn, transaction))
{
cmd.Parameters.AddWithValue("@TicketsCount", ticketsCount);
cmd.Parameters.AddWithValue("@TripID", tripID);
cmd.ExecuteNonQuery();
}
}
Также для авторизованного пользователя реализована возможность просмотра истории оформленных заказов (Рисунок 38).
Рисунок 38- Просмотр истории заказов