
ПИс6
.docxГУАП
КАФЕДРА № 14
ОТЧЕТ ЗАЩИЩЕН С ОЦЕНКОЙ
ПРЕПОДАВАТЕЛЬ
Старший преподаватель |
|
|
|
Н. В. Барклаевская |
должность, уч. степень, звание |
|
подпись, дата |
|
инициалы, фамилия |
ОТЧЕТ О ЛАБОРАТОРНОЙ РАБОТЕ №6 |
СОЗДАНИЕ САЙТА С ИСПОЛЬЗОВАНИЕМ ТЕХНОЛОГИИ ASP.NET. ЧАСТЬ 2. РЕАЛИЗАЦИЯ ЛИЧНОГО КАБИНЕТА ПОЛЬЗОВАТЕЛЯ |
по курсу: ПРОЕКТИРОВАНИЕ ИНФОРМАЦИОННЫХ СИСТЕМ |
|
|
РАБОТУ ВЫПОЛНИЛ
СТУДЕНТ гр. № |
4116 |
|
|
|
|
|
|
|
подпись, дата |
|
инициалы, фамилия |
Санкт-Петербург 2024
Цель работы: создание сайта с использованием технологии ASP.NET, разработка страницы регистрации пользователя, авторизации пользователя, реализация оформления заказа услуги или товара, просмотр ранее выполненных заказов, редактирование данных пользователя.
Описание предметной области:
Туристическое агентство представляет собой организацию, которая занимается продажей туристических путёвок. Основными задачами агентства являются поиск и разработка туров, консультирование клиентов, оформление бронирований, обеспечение процесса оплаты и предоставление актуальной информации о турах и предложениях.
Реализована регистрация пользователей. Данных из формы, проверяется их корректность, выполняется подключение к базе данных, вычисляется новый идентификатор клиента, данные заносятся в таблицу Client. (Рисунок -21).
Рисунок 1- Форма регистрации пользователей
На рисунке 2 показано добавление пользователя в таблицу Клиент
Рисунок 2 – Добавление пользователя в таблицу Клиент
Листинг 1- Команда кнопки регистрации пользователя
protected void btnRegister_Click(object sender, EventArgs e)
{
// считывание данных из полей формы
string name = txtName.Text.Trim();
string surname = txtSurname.Text.Trim();
string patronymic = txtPatronymic.Text.Trim();
string dobText = txtDOB.Text.Trim();
string phone = txtPhone.Text.Trim();
string login = txtLogin.Text.Trim();
string password = txtPassword.Text.Trim();
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(surname) || string.IsNullOrEmpty(phone) || string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password))
{
lblMessage.Text = "Все поля должны быть заполнены.";
return;
}
if (!DateTime.TryParse(dobText, out DateTime dob))
{
lblMessage.Text = "Некорректная дата рождения.";
return;
}
string connectionString = "Data Source=localhost;Initial Catalog=travel;Integrated Security=True";
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string maxIdQuery = "SELECT ISNULL(MAX(Client_ID), 0) + 1 FROM Client";
int newClientID;
using (SqlCommand maxIdCommand = new SqlCommand(maxIdQuery, connection))
{
newClientID = (int)maxIdCommand.ExecuteScalar();
}
string insertQuery = "INSERT INTO Client (Client_ID, Name_C, Surname_C, Patronymic_C, DOB_C, Phone_C, LoginC, PasswordC) " + "VALUES (@ClientID, @Name, @Surname, @Patronymic, @DOB, @Phone, @Login, @Password)";
using (SqlCommand insertCommand = new SqlCommand(insertQuery, connection))
{
insertCommand.Parameters.AddWithValue("@ClientID", newClientID);
insertCommand.Parameters.AddWithValue("@Name", name);
insertCommand.Parameters.AddWithValue("@Surname", surname);
insertCommand.Parameters.AddWithValue("@Patronymic", patronymic);
insertCommand.Parameters.AddWithValue("@DOB", dob);
insertCommand.Parameters.AddWithValue("@Phone", phone);
insertCommand.Parameters.AddWithValue("@Login", login);
insertCommand.Parameters.AddWithValue("@Password", password);
int rowsAffected = insertCommand.ExecuteNonQuery();
if (rowsAffected > 0)
{
lblMessage.ForeColor = System.Drawing.Color.Green;
lblMessage.Text = "Регистрация прошла успешно!";
}
else
{
lblMessage.Text = "Ошибка регистрации. Попробуйте снова.";
}
}
}
}
catch (Exception ex)
{
lblMessage.Text = "Ошибка: " + ex.Message;
}
}
Затем реализована авторизация пользователя (Рисунок 3-4). При нажатии на кнопку Вход, выполняется проверка логина и пароля пользователя в базе данных, если данные корректны, программа сохраняет информацию о пользователе в сессии и перенаправляет на главную страницу, если неверны, отображает сообщение об ошибке (Листинг 2).
Также написана функция для проверки, авторизован ли пользователь, в зависимости от этого, появляются или скрываются элементы интерфейса. Также реализовано приветствие пользователя, если он вошел в систему. После нажатии авторизованного пользователя на кнопку Выход, происходит очищение данных сессии, и элементы интерфейса становятся видимыми для неавторизованного пользователя (Листинг 3)
Рисунок 3 – Главная страница до авторизации
Рисунок 4 - Главная страница после авторизации пользователя
Листинг 2- Функция кнопки входа
protected void btnLogin_Click(object sender, EventArgs e)
{
string login = txtUsername.Text.Trim();
string password = txtPassword.Text.Trim();
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password))
{
lblMessage.Text = "Введите логин и пароль.";
lblMessage.ForeColor = System.Drawing.Color.Red;
return;
}
string connectionString = "Data Source=localhost;Initial Catalog=travel;Integrated Security=True";
string query = @"
SELECT 'Client' AS UserType, Client_ID AS UserId, Name_C AS FirstName
FROM Client WHERE LoginC = @Login AND PasswordC = @Password
UNION ALL
SELECT 'Employee' AS UserType, Employee_ID AS UserId, Name_E AS FirstName
FROM Employee WHERE LoginE = @Login AND PasswordE = @Password";
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand(query, connection))
{
command.Parameters.AddWithValue("@Login", login);
command.Parameters.AddWithValue("@Password", password);
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
// Сохранение данных в сессии
Session["UserType"] = reader["UserType"].ToString();
Session["UserId"] = reader["UserId"].ToString();
Session["UserName"] = reader["FirstName"].ToString();
lblMessage.ForeColor = System.Drawing.Color.Green;
lblMessage.Text = "Вход выполнен успешно!";
Response.Redirect("Home.aspx");
}
else
{
lblMessage.Text = "Неверный логин или пароль.";
lblMessage.ForeColor = System.Drawing.Color.Red;
}
}
}
}
catch (Exception ex)
{
lblMessage.Text = "Ошибка: " + ex.Message;
lblMessage.ForeColor = System.Drawing.Color.Red;
}
}
Листинг 3- Функция кнопки выхода
protected void btnLogout_Click(object sender, EventArgs e)
{
Session.Clear();
txtUsername.Visible = true;
txtPassword.Visible = true;
lblLogin.Visible = true;
lblPassword.Visible = true;
btnLogin.Visible = true;
btnRegister.Visible = true;
btnLogout.Visible = false;
lblMessage.Text = "Вы успешно вышли.";
lblMessage.ForeColor = System.Drawing.Color.Green;
Response.Redirect("Home.aspx");
}
Дале создана возможность оформления заказа пользователем. При выборе определенного тура, происходит переход на страницу этого тура. На странице тура есть возможно выбора дат для путешествия и проверки количества доступных путевок (Рисунок 5). При выборе дат и количества путевок пользователь получает сообщение о доступности или отсутствии путевок (Рисунок 6-7).
Рисунок 5- Страница тура и выбора дат
Рисунок 6 - Получение сообщения о доступности поездки
Рисунок 7- Сообщение о недоступности мест
Листинг 4- Функция для проверки доступности мест для бронирования на выбранную дату
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;
}
}
}
}
При нажатии на кнопку «Перейти к оформлению заказа» открывается форма для заполнения данных пассажиров (Рисунок 8). В зависимости от количества путевок создаются текстовые поля и метки для ввода информации о пассажирах. Также рассчитывается общая стоимость тура, умножая цену одной путевки на количество путевок (Листинг 5).
Рисунок 8- Подробная информация о туре
Листинг 5- Функция расчета стоимости
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}";
}
}
При правильно заполненных данных, создается запись в таблице Заказ (Листинг 6), а в таблицу с путевками заносятся данные о пассажирах, которые привязаны к путевке (Листинг 7). Также при оформлении заказа, уменьшается количество доступных путевок (Листинг 8) (Рисунок 9-12).
Рисунок 9- Таблица с доступными путевками до оформления заказа
Рисунок 10- Успешное оформление заказа
Рисунок 11- Таблица с доступными путевками после оформления заказа
Рисунок
12- Таблицами с путевками
Листинг 6- Функция для создания записи в таблице с заказами
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();
}
}
Листинг 7 – Добавление оформленных путевок в таблицу с путевками
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();
}
}
}
Листинг 8- Функция уменьшения количества доступных путевок
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();
}
}
Также для авторизованного пользователь реализована возможность просмотра истории оформленных заказов (Рисунок 13).
Рисунок 13- Просмотр истории заказов
Листинг 9- Функция отображения истории заказов для текущего пользователя
protected void LoadOrderHistory()
{
string connectionString = "Data Source=localhost;Initial Catalog=travel;Integrated Security=True";
string query = @"
SELECT
Order_data.Order_ID,
Tour.Name_T AS TourName,
Tour.Description_T AS Description,
Trip.StartDate AS StartDate,
Trip.EndDate AS EndDate,
STRING_AGG(
Permit.LastName + ' ' + Permit.FirstName +
ISNULL(' ' + Permit.MiddleName, '') +
' (Дата рождения: ' + FORMAT(Permit.DOB, 'dd.MM.yyyy') + ')',
'<br/>'
) AS PassengerInfo,
(Trip.Price * Order_data.PeopleCount) AS TotalPrice,
Type_T.Name_T AS TourType,
Season.Name_Season AS Season,
Hotel.Name_H AS HotelName,
Locality.Name_L AS RouteLocality,
Locality.Country AS Country,
ISNULL(Image.FilePath, 'default.jpg') AS ImagePath
FROM
Order_data
INNER JOIN
Trip ON Order_data.Trip_ID = Trip.Trip_ID
INNER JOIN
Tour ON Trip.Tour_ID = Tour.Tour_ID
INNER JOIN
Permit ON Order_data.Order_ID = Permit.Order_ID
INNER JOIN
Type_T ON Tour.TypeT_ID = Type_T.TypeT_ID
INNER JOIN
TourSeason ON Tour.Tour_ID = TourSeason.Tour_ID
INNER JOIN
Season ON TourSeason.Season_ID = Season.Season_ID
INNER JOIN
TourHotel ON Tour.Tour_ID = TourHotel.Tour_ID
INNER JOIN
Hotel ON TourHotel.Hotel_ID = Hotel.Hotel_ID
INNER JOIN
Route ON Tour.Tour_ID = Route.Tour_ID
INNER 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
WHERE
Order_data.Client_ID = @ClientID
GROUP BY
Order_data.Order_ID,
Tour.Name_T,
Tour.Description_T,
Trip.StartDate,
Trip.EndDate,
Trip.Price,
Order_data.PeopleCount,
Type_T.Name_T,
Season.Name_Season,
Hotel.Name_H,
Locality.Name_L,
Locality.Country,
Image.FilePath;";
try
{
int clientId = int.Parse(Session["UserId"].ToString());
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("@ClientID", clientId);
SqlDataAdapter adapter = new SqlDataAdapter(command);
DataTable dt = new DataTable();
adapter.Fill(dt);
if (dt.Rows.Count > 0)
{
gvOrderHistory.DataSource = dt;
gvOrderHistory.DataBind();
}
else
{
lblMessage.Text = "У вас пока нет заказов.";
}
}
}
catch (Exception ex)
{
lblMessage.Text = "Ошибка загрузки данных: " + ex.Message;
}
}
При переходе на страницу Редактирование профиля, пользователь может изменить свои данные (Рисунок 14-16).
Рисунок 14- Форма для редактирования данных пользователя
Рисунок 15- Обновление номера телефона пользователя
Рисунок 16- Проверка обновления данных
Листинг 10- Функция обновления данных
protected void btnSave_Click(object sender, EventArgs e)
{
if (Session["UserId"] == null)
{
lblMessage.Text = "Вы не авторизованы. Пожалуйста, войдите в систему.";
return;
}
int clientId = int.Parse(Session["UserId"].ToString());
string connectionString = "Data Source=localhost;Initial Catalog=travel;Integrated Security=True";
string query = @"
UPDATE Client
SET Name_C = @Name,
Surname_C = @Surname,
Patronymic_C = @Patronymic,
DOB_C = @DOB,
Phone_C = @Phone
WHERE Client_ID = @ClientID";
try
{
using (SqlConnection connection = new SqlConnection(connectionString))
{ SqlCommand command = new SqlCommand(query, connection);
command.Parameters.AddWithValue("@Name", txtName.Text);
command.Parameters.AddWithValue("@Surname", txtSurname.Text);
command.Parameters.AddWithValue("@Patronymic", txtPatronymic.Text);
command.Parameters.AddWithValue("@DOB", Convert.ToDateTime(txtDOB.Text));
command.Parameters.AddWithValue("@Phone", txtPhone.Text);
command.Parameters.AddWithValue("@ClientID", clientId);
connection.Open();
int rowsAffected = command.ExecuteNonQuery();
if (rowsAffected > 0)
{
lblSuccess.Text = "Данные успешно обновлены!";
lblMessage.Text = "";
}
else
{
lblMessage.Text = "Ошибка обновления данных.";
}
}
}
catch (Exception ex)
{
lblMessage.Text = "Ошибка сохранения данных: " + ex.Message;
}
}
}
Вывод: созданы странницы сайта с использованием технологии ASP.NET, разработаны страницы регистрации пользователя, авторизации пользователя, оформления заказа услуги или товара, просмотра ранее выполненных заказов, редактирования данных пользователя.