Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
отчет летняя практика 3 курс.docx
Скачиваний:
0
Добавлен:
11.02.2026
Размер:
3.5 Mб
Скачать

Основания для разработки

Основанием для разработки является актуальность десктопного приложения для работы с пешими туристическими походами. Оно является необходимым шагом для повышения качества организации походов, обеспечения безопасности участников, а также оптимизации оперативного управления. Приложение отвечает современным требованиям, которые предъявляют как туристы, так и инструкторы, и способствует развитию культуры активного отдыха.

Назначение разработки

Десктопное приложение будет использоваться для упрощения работы с организацией пеших походов, учета доходов и расходов, бронирования и покупки пеших туров.

Технические требования к программному изделию Требования к функциональным характеристикам

Программный продукт должен выполнять базовый функционал:

        1. Просмотр и покупка пеших туристических походов

        2. Выбор оборудования для аренды

        3. Оценивание похода после прохождения

        4. Описание поврежденного оборудования

        5. Добавление и редактирование маршрутов

        6. Добавление и редактирование учетных записей инструктора

        7. Просмотр статистики о посещении всех маршрутов

        8. Просмотр людей, посещавших выбранный маршрут

        9. Просмотр финансового отчета по проданным маршрутам за выбранный период

Требования к надежности

Пользователю, работающему с программой, должен быть предоставлен непрерывный доступ ко всей информации о маршрутах. Программа не должна непрерывно прерывать свою работу.

Условия эксплуатации

Климатические условия

Требования к климатическим условиям эксплуатации не требуются.

Требования к видам обслуживания

Требования к обслуживанию отсутствуют.

Требования к численности и квалификации персонала

Для управления системой достаточно одного человека, способного запустить программу. Требуемая квалификация пользователя – уверенный пользователь персонального компьютера.

Требования к составу и параметрам технических средств

Для корректной работы приложения требуется операционная система «Windows 10» и выше.

Требования к информационной и программной совместимости

Требования к исходным кодам и языка программирования

Исходные коды программы должны быть написаны на языке C# в среде разработки Microsoft Visual Studio 2022 и выше, с установленными компонентами «.NET FrameWork 8.0» или «.NET Core 8.0»

Требования к программным средствам, используемые программой

Системные программные средства, используемые программой, должны быть представлены лицензионной локализованной версией операционной системы не ниже «Windows 10».

Требования к маркировке и упаковке

Программа представляется в виде EXE-файла и не требует упаковки. Требования к упаковке и маркировке не предоставляются.

Требования к транспортировке и хранению

Приложение храниться на Интернет-ресурсе --: ссылка. Специальные требования к транспортировке и хранению не требуются.

Требования к программной документации

Состав программной документации

  • «Приложение для походов». Техническое задание (ГОСТ 19.201-78, ГОСТ 34.602-89);

  • «Приложение для походов». Текст программы (ГОСТ 19.401-78)

Специальные требования к программной документации

Вся документация должна быть оформлена в соответствии с вышеуказанными ГОСТами, к каждому виду документа (см. предыдущий пункт).

Технико-экономические показатели

В рамках данной работы технико-экономические показатели не рассчитывались.

Состав и содержание этапов работ по созданию приложения для походов

Таблица 1 – Перечень стадий и этапов разработки.

Этап работ

Документы, предъявленные к результатам

Сроки выполнения

1

Ознакомление с идеологией и принципами составления пеших туристических походов

01.10.2024

2

Написание ТЗ

Техническое задание по ГОСТ 19.201-78

14.05.2025

3

Описание системы работы десктопного приложения в UML

4

Реализация прототипа интерфейса приложения

13.05.2025

5

Реализация базового интерфейса приложения

Текст программы по ГОСТ 19.401-78

26.05.2025

Приложение 2. Листинг

Часть пользователя-туриста.

Файл buyingtours.cs

using iTextSharp.text.pdf;

using iTextSharp.text;

using MySql.Data.MySqlClient;

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

namespace рпп_приложение_В_ПОХОД

{

public partial class buyingtour : Form

{

private const string connectionString = "server=localhost;database=hikingtrips;uid=root;password=Fuckingpassword2;";

private DataGridViewCell clickedCell;

int selectedIndex1;

int selectedIndex2;

double days;

int x;

private static readonly Random rnd = new Random();

int cost = rnd.Next(500, 5000);

int instr = rnd.Next(1, 6);

int paidornot = 1;

int usertripid;

public buyingtour(int usr_ind)

{

InitializeComponent();

this.x = usr_ind;

LoadRoutes();

LoadEquipment();

}

private void button5_Click(object sender, EventArgs e)

{

DateTime dt = dateTimePicker1.Value;

DateTime new_dt = dt.Date;

ExportSelectedRouteToPdf(new_dt);

}

private void LoadRoutes()

{

using (MySqlConnection connection = new MySqlConnection(connectionString))

{

connection.Open();

string query = "SELECT * FROM routes";

using (MySqlCommand command = new MySqlCommand(query, connection))

{

MySqlDataAdapter adapter = new MySqlDataAdapter(command);

DataTable routesTable = new DataTable();

adapter.Fill(routesTable);

dataGridView1.DataSource = routesTable;

}

}

}

private void LoadEquipment()

{

using (MySqlConnection connection = new MySqlConnection(connectionString))

{

connection.Open();

string query = "SELECT * FROM equipment";

using (MySqlCommand command = new MySqlCommand(query, connection))

{

MySqlDataAdapter adapter = new MySqlDataAdapter(command);

DataTable routesTable = new DataTable();

adapter.Fill(routesTable);

dataGridView2.DataSource = routesTable;

}

}

}

public void ExportSelectedRouteToPdf(DateTime new_dt)

{

Document document = new Document();

PdfWriter.GetInstance(document, new System.IO.FileStream(@"C:\Users\ACER\Desktop\receipt.pdf", System.IO.FileMode.Create));

BaseFont baseFont = BaseFont.CreateFont(

@"c:\Windows\Fonts\times.ttf",

BaseFont.IDENTITY_H,

BaseFont.EMBEDDED);

iTextSharp.text.Font russianFont = new iTextSharp.text.Font(baseFont, 12, iTextSharp.text.Font.NORMAL);

int ind = x;

if (dataGridView1.SelectedRows.Count > 0)

{

if (dataGridView2.SelectedRows.Count > 0)

{

selectedIndex1 = Convert.ToInt32(dataGridView1.SelectedRows[0].Cells["route_id"].Value);

selectedIndex2 = Convert.ToInt32(dataGridView2.SelectedRows[0].Cells["equipment_id"].Value);

using (MySqlConnection connection2 = new MySqlConnection(connectionString))

{

string query2 = "SELECT last_name, first_name, middle_name FROM costumers WHERE user_id = @ind";

MySqlCommand command2 = new MySqlCommand(query2, connection2);

command2.Parameters.AddWithValue("@ind", ind);

connection2.Open();

MySqlDataReader reader2 = command2.ExecuteReader();

document.Open();

if (reader2.Read())

{

string f = reader2["last_name"].ToString();

string i = reader2["first_name"].ToString();

string o = reader2["middle_name"].ToString();

document.Add(new Paragraph("Информация о купленном туре", russianFont));

document.Add(new Paragraph($"{f} " + $"{i} " + $"{o}, " + "сообщаем вам, что вы приобрели маршрут и арендовали снаряжение для пешего тура. Информацию о своих покупках вы найдете в квитанции ниже.", russianFont));

document.Add(new Paragraph(" "));

}

reader2.Close();

connection2.Close();

}

using (MySqlConnection connection = new MySqlConnection(connectionString))

{

string query = "SELECT title, duration_in_hours, duration_in_days ,point_of_departure, price FROM routes WHERE route_id = @index";

MySqlCommand command = new MySqlCommand(query, connection);

command.Parameters.AddWithValue("@index", selectedIndex1);

connection.Open();

MySqlDataReader reader = command.ExecuteReader();

if (reader.Read())

{

string title = reader["title"].ToString();

string duration_in_hours = reader["duration_in_hours"].ToString();

string duration_in_days = reader["duration_in_days"].ToString();

string point_of_departure = reader["point_of_departure"].ToString();

string price = reader["price"].ToString();

document.Add(new Paragraph($"Информация о приобретенном туристическом походе:", russianFont));

document.Add(new Paragraph($"Название: {title}", russianFont));

document.Add(new Paragraph($"Длительность в часах: {duration_in_hours} часов", russianFont));

document.Add(new Paragraph($"Длительность в днях: {duration_in_days} дней", russianFont));

document.Add(new Paragraph($"Точка отправления: {point_of_departure}", russianFont));

document.Add(new Paragraph($"Стоимость: {price} рублей", russianFont));

document.Add(new Paragraph(" "));

days = Convert.ToDouble(duration_in_days);

}

reader.Close();

connection.Close();

}

using (MySqlConnection connection3 = new MySqlConnection(connectionString))

{

string query3 = "SELECT title, amount FROM equipment WHERE equipment_id = @index";

MySqlCommand command3 = new MySqlCommand(query3, connection3);

command3.Parameters.AddWithValue("@index", selectedIndex2);

connection3.Open();

MySqlDataReader reader3 = command3.ExecuteReader();

if (reader3.Read())

{

string title = reader3["title"].ToString();

document.Add(new Paragraph($"Информация об арендованном оборудовании:", russianFont));

document.Add(new Paragraph($"Название: {title}", russianFont));

document.Add(new Paragraph($"Цена: {cost} рублей", russianFont));

document.Add(new Paragraph(" "));

}

reader3.Close();

connection3.Close();

}

using (MySqlConnection connection6 = new MySqlConnection(connectionString))

{

string query6 = "SELECT * FROM instructors WHERE instructor_id = @index";

MySqlCommand command6 = new MySqlCommand(query6, connection6);

command6.Parameters.AddWithValue("@index", instr);

connection6.Open();

MySqlDataReader reader6 = command6.ExecuteReader();

if (reader6.Read())

{

string last_name = reader6["last_name"].ToString();

string first_name = reader6["first_name"].ToString();

string middle_name = reader6["middle_name"].ToString();

string phone_number = reader6["phone_number"].ToString();

string email = reader6["email"].ToString();

string seniority = reader6["seniority"].ToString();

document.Add(new Paragraph($"Информация о вашем инструкторе:", russianFont));

document.Add(new Paragraph($"Имя: {last_name} " + $"{first_name} " + $"{middle_name}", russianFont));

document.Add(new Paragraph($"Номер телефона: {phone_number}", russianFont));

document.Add(new Paragraph($"Почта: {email}", russianFont));

document.Add(new Paragraph($"Рабочий стаж: {seniority} лет", russianFont));

document.Add(new Paragraph(" "));

}

reader6.Close();

connection6.Close();

}

using (MySqlConnection connection4 = new MySqlConnection(connectionString))

{

connection4.Open();

string query4 = "INSERT INTO teams (trip, user, instructor, paid_or_not) VALUES (@trip, @user, @instructor, @paid_or_not)";

string query6 = "SELECT user_trip_id FROM teams WHERE user = @index";

using (MySqlCommand command = new MySqlCommand(query4, connection4))

{

command.Parameters.AddWithValue("@trip", selectedIndex1);

command.Parameters.AddWithValue("@user", ind);

command.Parameters.AddWithValue("@instructor", instr);

command.Parameters.AddWithValue("@paid_or_not", paidornot);

command.ExecuteNonQuery();

}

using (MySqlCommand command2 = new MySqlCommand(query6, connection4))

{

command2.Parameters.AddWithValue("@index", ind);

usertripid = Convert.ToInt32(command2.ExecuteScalar());

}

connection4.Close();

}

using (MySqlConnection connection5 = new MySqlConnection(connectionString))

{

connection5.Open();

string query5 = "INSERT INTO rent (user_on_trip, equipment, price) VALUES (@user_on_trip, @equipment, @price)";

using (MySqlCommand command = new MySqlCommand(query5, connection5))

{

command.Parameters.AddWithValue("@user_on_trip", usertripid);

command.Parameters.AddWithValue("@equipment", selectedIndex2);

command.Parameters.AddWithValue("@price", cost);

command.ExecuteNonQuery();

}

connection5.Close();

}

}

using (MySqlConnection connection = new MySqlConnection(connectionString))

{

connection.Open();

string query = "INSERT INTO trip (route, date_of_begining, date_of_ending) VALUES (@route, @date_of_begining, @date_of_ending)";

using (MySqlCommand command = new MySqlCommand(query, connection))

{

DateTime endDate = new_dt.AddDays(days);

command.Parameters.AddWithValue("@route", selectedIndex1);

command.Parameters.AddWithValue("@date_of_begining", new_dt.ToString("yyyy-MM-dd"));

command.Parameters.AddWithValue("@date_of_ending", endDate.ToString("yyyy-MM-dd"));

command.ExecuteNonQuery();

}

}

using (MySqlConnection connection7 = new MySqlConnection(connectionString))

{

string query7 = "SELECT date_of_begining, date_of_ending FROM trip WHERE trip_id = (SELECT MAX(trip_id) FROM trip)";

MySqlCommand command7 = new MySqlCommand(query7, connection7);

connection7.Open();

MySqlDataReader reader7 = command7.ExecuteReader();

if (reader7.Read())

{

string date_of_begining = reader7["date_of_begining"].ToString();

string date_of_ending = reader7["date_of_ending"].ToString();

document.Add(new Paragraph($"Информация о датах, которые вы выбрали для поездки:", russianFont));

document.Add(new Paragraph($"Дата начала: {date_of_begining}", russianFont));

document.Add(new Paragraph($"Дата окончания: {date_of_ending}", russianFont));

document.Close();

}

reader7.Close();

connection7.Close();

MessageBox.Show("PDF-документ успешно сохранен на рабочем столе!", "Успех!", MessageBoxButtons.OK, MessageBoxIcon.Information);

}

}

feedback frm6 = new feedback(usertripid);

frm6.Show();

this.Hide();

}

}

}

Часть инструктора.

Файл workspace.cs

using MySql.Data.MySqlClient;

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

using MySql.Data.MySqlClient;

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

using System;

using System.Drawing;

using System.IO;

using System.Windows.Forms;

using iTextSharp.text;

using iTextSharp.text.pdf;

using System.Drawing.Printing;

using System.Drawing;

using static System.Windows.Forms.VisualStyles.VisualStyleElement;

using static System.Runtime.InteropServices.JavaScript.JSType;

using System.Reflection.Metadata;

namespace рпп_приложение_В_ПОХОД

{

public partial class workspace : Form

{

private const string connectionString = "server=localhost;database=hikingtrips;uid=root;password=Fuckingpassword2;";

int selectedIndex1;

int selectedIndex2;

public workspace()

{

InitializeComponent();

LoadRoutes();

LoadEquipment();

}

private void button2_Click(object sender, EventArgs e) //show people on route

{

var pdfPath = "C:\\Users\\ACER\\Desktop\\PeopleOnRoutes.pdf";

peopleOnRoutesPDF();

MessageBox.Show($"PDF-файл со списком людей был успешно сохранен {pdfPath}");

}

private void button3_Click(object sender, EventArgs e) //show statistics

{

var data = GetDataFromDatabase();

var chartImage = CreateChart(data);

var pdfPath = "C:\\Users\\ACER\\Desktop\\RouteVisitReport.pdf";

SaveChartToPdf(chartImage, pdfPath);

MessageBox.Show($"PDF-файл с графиком был успешно сохранен {pdfPath}");

}

private void button5_Click(object sender, EventArgs e) //send description

{

string description = textBox1.Text;

damageDescription(description);

}

private void button6_Click(object sender, EventArgs e) //change user

{

autorizationinstructor au2 = new autorizationinstructor();

au2.Show();

this.Close();

}

private void button7_Click(object sender, EventArgs e) //exit

{

chooseuser ch3 = new chooseuser();

ch3.Show();

this.Close();

}

private void button8_Click(object sender, EventArgs e) //add route

{

addroute ar1 = new addroute();

ar1.Show();

this.Close();

}

private void button9_Click(object sender, EventArgs e) //change route

{

selectroutetochange ch1 = new selectroutetochange();

ch1.Show();

this.Close();

}

private void LoadRoutes()

{

using (MySqlConnection connection = new MySqlConnection(connectionString))

{

connection.Open();

string query = "SELECT route_id, title FROM routes";

using (MySqlCommand command = new MySqlCommand(query, connection))

{

MySqlDataAdapter adapter = new MySqlDataAdapter(command);

DataTable routesTable = new DataTable();

adapter.Fill(routesTable);

dataGridView1.DataSource = routesTable;

}

}

}

private void peopleOnRoutesPDF()

{

iTextSharp.text.Document document = new iTextSharp.text.Document();

PdfWriter.GetInstance(document, new System.IO.FileStream(@"C:\Users\ACER\Desktop\PeopleOnRoutes.pdf", System.IO.FileMode.Create));

if (dataGridView1.SelectedRows.Count > 0)

{

selectedIndex1 = Convert.ToInt32(dataGridView1.SelectedRows[0].Cells["route_id"].Value);

using (MySqlConnection connection2 = new MySqlConnection(connectionString))

{

string query2 = "SELECT c.last_name, c.first_name, c.middle_name, c.phone_number FROM costumers AS c JOIN teams AS tm ON c.user_id = tm.user JOIN trip AS tp ON tm.trip = tp.trip_id JOIN routes AS r ON tp.route = r.route_id WHERE r.route_id = @ind";

MySqlCommand command2 = new MySqlCommand(query2, connection2);

command2.Parameters.AddWithValue("@ind", selectedIndex1);

MySqlDataAdapter da = new MySqlDataAdapter(command2);

DataTable dt = new DataTable();

da.Fill(dt);

connection2.Open();

MySqlDataReader reader2 = command2.ExecuteReader();

if (reader2.Read())

{

document.Open();

document.Add(new Paragraph("Информация о людях, посетивших выбранный маршрут:"));

foreach (DataRow row in dt.Rows)

{

foreach (var item in row.ItemArray)

{

document.Add(new Paragraph(item.ToString()));

}

document.Add(new Paragraph(Environment.NewLine)); // Пустая строка между записями

}

document.Close();

}

reader2.Close();

connection2.Close();

}

}

}

private void LoadEquipment()

{

using (MySqlConnection connection = new MySqlConnection(connectionString))

{

connection.Open();

string query = "SELECT * FROM rent";

using (MySqlCommand command = new MySqlCommand(query, connection))

{

MySqlDataAdapter adapter = new MySqlDataAdapter(command);

DataTable routesTable = new DataTable();

adapter.Fill(routesTable);

dataGridView2.DataSource = routesTable;

}

}

}

private void damageDescription(string description)

{

if (dataGridView2.SelectedRows.Count > 0)

{

selectedIndex2 = Convert.ToInt32(dataGridView2.SelectedRows[0].Cells["rent_id"].Value);

using (MySqlConnection connection = new MySqlConnection(connectionString))

{

connection.Open();

string query = "INSERT INTO damage_of_equipment (description, rent) VALUES (@text, @rent)";

using (MySqlCommand command = new MySqlCommand(query, connection))

{

command.Parameters.AddWithValue("@text", Convert.ToString(description));

command.Parameters.AddWithValue("@rent", Convert.ToString(selectedIndex2));

command.ExecuteNonQuery();

}

}

}

MessageBox.Show("Описание созранено!", "Успех!", MessageBoxButtons.OK, MessageBoxIcon.Information);

}

private List<RouteVisitData> GetDataFromDatabase()

{

var routeVisits = new List<RouteVisitData>();

using (var connection = new MySqlConnection(connectionString))

{

connection.Open();

string query = "SELECT routes.title, count(teams.user) from teams INNER JOIN routes ON route_id = teams.trip GROUP BY title";

using (var command = new MySqlCommand(query, connection))

{

using (var reader = command.ExecuteReader())

{

while (reader.Read())

{

routeVisits.Add(new RouteVisitData

{

RouteName = reader.GetString(0),

TotalVisitors = reader.IsDBNull(1) ? 0 : reader.GetInt32(1)

});

}

}

}

}

return routeVisits;

}

private Bitmap CreateChart(List<RouteVisitData> data)

{

var bitmap = new Bitmap(800, 600);

using (var graphics = Graphics.FromImage(bitmap))

{

graphics.Clear(Color.White);

Pen pen = new Pen(Color.Blue, 2);

int margin = 50;

int maxVisitors = 0;

// Определяем максимальное значение для нормализации графика

foreach (var entry in data)

{

if (entry.TotalVisitors > maxVisitors)

{

maxVisitors = entry.TotalVisitors;

}

}

// Рисуем оси

graphics.DrawLine(Pens.Black, margin, margin, margin, bitmap.Height - margin);

graphics.DrawLine(Pens.Black, margin, bitmap.Height - margin, bitmap.Width - margin, bitmap.Height - margin);

// Рисуем график

int barWidth = (bitmap.Width - 2 * margin) / data.Count;

for (int i = 0; i < data.Count; i++)

{

// Определяем координаты и размеры столбца

int x = margin + i * barWidth;

int y = bitmap.Height - margin - (data[i].TotalVisitors * (bitmap.Height - 2 * margin) / maxVisitors);

int height = bitmap.Height - margin - y;

// Заполняем столбец цветом

graphics.FillRectangle(Brushes.Blue, x, y, barWidth - 5, height);

// Пишем индекс маршрута над столбцом

graphics.DrawString(i.ToString(), new System.Drawing.Font("Arial", 10), Brushes.Black, x + (barWidth - 5) / 2 - 10, y - 20);

}

}

return bitmap;

}

private void SaveChartToPdf(Bitmap chartImage, string pdfPath)

{

using (FileStream stream = new FileStream(pdfPath, FileMode.Create))

{

using (MySqlConnection connection2 = new MySqlConnection(connectionString))

{

string query = "SELECT routes.title, count(teams.user) from teams INNER JOIN routes ON route_id = teams.trip GROUP BY title";

MySqlCommand command2 = new MySqlCommand(query, connection2);

MySqlDataAdapter da2 = new MySqlDataAdapter(command2);

DataTable dt2 = new DataTable();

da2.Fill(dt2);

connection2.Open();

MySqlDataReader reader2 = command2.ExecuteReader();

if (reader2.Read())

{

iTextSharp.text.Document pdfDoc = new iTextSharp.text.Document(iTextSharp.text.PageSize.A3, 10, 10, 10, 10);

PdfWriter.GetInstance(pdfDoc, stream);

pdfDoc.Open();

iTextSharp.text.Image pdfImage = iTextSharp.text.Image.GetInstance(chartImage, System.Drawing.Imaging.ImageFormat.Png);

pdfDoc.Add(pdfImage);

int i = 0; //нумерация

int j = 0; //итерация

foreach (DataRow row in dt2.Rows)

{

foreach (var item in row.ItemArray)

{

if (j % 2 == 0)

{

pdfDoc.Add(new Paragraph($"{i}: {item.ToString()}"));

i++;

j++;

}

else

{

pdfDoc.Add(new Paragraph($"Количество посещений: {item.ToString()}"));

j++;

}

}

pdfDoc.Add(new Paragraph(Environment.NewLine));

}

pdfDoc.Close();

}

}

}

}

public class RouteVisitData

{

public string RouteName { get; set; }

public int TotalVisitors { get; set; }

}

}

}

Часть администратора.

Файл adminworkspace.cs

using iTextSharp.text.pdf;

using iTextSharp.text;

using MySql.Data.MySqlClient;

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

namespace рпп_приложение_В_ПОХОД

{

public partial class adminworkspace : Form

{

private const string connectionString = "server=localhost;database=hikingtrips;uid=root;password=Fuckingpassword2;";

public adminworkspace()

{

InitializeComponent();

}

private void button1_Click(object sender, EventArgs e) //financial report routes

{

DateTime begin_date = dateTimePicker1.Value;

DateTime end_date = dateTimePicker2.Value;

GenerateFinancialReport(begin_date, end_date);

}

private void button2_Click(object sender, EventArgs e) //editing tourists

{

choosetourist ct1 = new choosetourist();

ct1.Show();

this.Hide();

}

private void button3_Click(object sender, EventArgs e) //editing instructors

{

chooseinstructorcs ci1 = new chooseinstructorcs();

ci1.Show();

this.Hide();

}

private void button5_Click(object sender, EventArgs e) //add instructor

{

addinstructor ai1 = new addinstructor();

ai1.Show();

this.Hide();

}

private void button4_Click(object sender, EventArgs e) //exit

{

chooseuser ch3 = new chooseuser();

ch3.Show();

this.Close();

}

public void GenerateFinancialReport(DateTime startDate, DateTime endDate)

{

// Получаем данные о покупках за период

DataTable reportData = GetReportData(startDate, endDate);

if (reportData.Rows.Count == 0)

{

MessageBox.Show("Нет данных для отчета за выбранный период");

return;

}

// Создаем документ PDF

Document document = new Document(PageSize.A4, 50, 50, 25, 25);

// Путь для сохранения на рабочий стол

string path = "C:\\Users\\ACER\\Desktop\\FinancialReportRoutes.pdf";

try

{

// Создаем PDF writer

PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(path, FileMode.Create));

// Открываем документ

document.Open();

BaseFont baseFont = BaseFont.CreateFont(

@"c:\Windows\Fonts\times.ttf",

BaseFont.IDENTITY_H,

BaseFont.EMBEDDED);

iTextSharp.text.Font russianFont = new iTextSharp.text.Font(baseFont, 12, iTextSharp.text.Font.NORMAL);

// Добавляем заголовок

Paragraph title = new Paragraph("ФИНАНСОВЫЙ ОТЧЕТ ПО ПРОДАЖАМ ТУРОВ", russianFont);

title.Alignment = Element.ALIGN_CENTER;

title.SpacingAfter = 20f;

document.Add(title);

// Добавляем период отчета

Paragraph period = new Paragraph(

$"Период: {startDate:dd.MM.yyyy} - {endDate:dd.MM.yyyy}", russianFont);

period.Alignment = Element.ALIGN_CENTER;

period.SpacingAfter = 15f;

document.Add(period);

// Создаем таблицу для данных

PdfPTable table = new PdfPTable(5); // 5 колонок

table.WidthPercentage = 100;

table.SpacingBefore = 10f;

table.SpacingAfter = 10f;

// Настройка заголовков таблицы

string[] headers = { "ID поездки", "Название тура", "Дата начала", "Дата окончания", "Стоимость" };

foreach (string header in headers)

{

PdfPCell cell = new PdfPCell(new Phrase(header, russianFont));

cell.BackgroundColor = new BaseColor(200, 200, 200);

cell.HorizontalAlignment = Element.ALIGN_CENTER;

table.AddCell(cell);

}

// Заполняем таблицу данными

decimal total = 0;

foreach (DataRow row in reportData.Rows)

{

table.AddCell(new Phrase(row["trip_id"].ToString()));

table.AddCell(new Phrase(row["route_name"].ToString()));

table.AddCell(new Phrase(Convert.ToDateTime(row["date_of_begining"]).ToString("dd.MM.yyyy")));

table.AddCell(new Phrase(Convert.ToDateTime(row["date_of_ending"]).ToString("dd.MM.yyyy")));

decimal price = Convert.ToDecimal(row["price"]);

table.AddCell(new Phrase(price.ToString("C")));

total += price;

}

document.Add(table);

// Добавляем итоговую сумму

Paragraph totalParagraph = new Paragraph(

$"Общая сумма продаж: {total.ToString("C")}", russianFont);

totalParagraph.Alignment = Element.ALIGN_RIGHT;

totalParagraph.SpacingBefore = 10f;

document.Add(totalParagraph);

// Добавляем дату генерации отчета

Paragraph dateParagraph = new Paragraph(

$"Отчет сгенерирован: {DateTime.Now:dd.MM.yyyy HH:mm}", russianFont);

dateParagraph.Alignment = Element.ALIGN_RIGHT;

document.Add(dateParagraph);

MessageBox.Show($"Отчет успешно сохранен на рабочий стол:\n{path}");

}

catch (Exception ex)

{

MessageBox.Show($"Ошибка при создании отчета: {ex.Message}");

}

finally

{

document.Close();

}

}

private DataTable GetReportData(DateTime startDate, DateTime endDate)

{

DataTable data = new DataTable();

try

{

using (MySqlConnection connection = new MySqlConnection(connectionString))

{

string query = @"

SELECT

t.trip_id,

r.title AS route_name,

t.date_of_begining,

t.date_of_ending,

r.price

FROM

trip t

JOIN routes r ON t.route = r.route_id

WHERE

t.date_of_begining BETWEEN @StartDate AND @EndDate

ORDER BY

t.date_of_begining"

;

MySqlCommand command = new MySqlCommand(query, connection);

command.Parameters.AddWithValue("@StartDate", startDate);

command.Parameters.AddWithValue("@EndDate", endDate);

MySqlDataAdapter adapter = new MySqlDataAdapter(command);

adapter.Fill(data);

}

}

catch (Exception ex)

{

MessageBox.Show($"Ошибка при получении данных для отчета: {ex.Message}");

}

return data;

}

}

}

Приложение 3. Руководство пользователя

Часть пользователя-туриста.

При запуске приложения появится окно с выбором пользователя, показанное на рис. 17. Чтоб зайти как турист необходимо нажать на кнопку «Турист».

Рис. 17. Окно с выбором пользователя.

Далее откроется окно с вопросом, что пользователь хочет сделать: зарегистрироваться или войти в систему. Это окно показано на рис. 18. В данном случае будет рассмотрен сценарий того, что пользователя нет в базе и он регистрируется первый раз. Для этого необходимо нажать на кнопку «Зарегистрироваться».

Рис. 18. Окно с предложением зарегистрироваться или войти в систему.

Открывается окно, в которое необходимо ввести личные данные туриста. Окно представлено на рис. 19.

Рис. 19. Окно с полями для ввода данных туриста.

После завершения ввода данных необходимо нажать на кнопку «Сохранить», успешное сохранение данных будет сопровождаться оповещением. Окно и оповещение представлены на рис. 20.

Рис. 20. Оповещение о том, что данные были успешно добавлены.

Теперь необходимо ввести логин и пароль, по которым пользователь сможет попасть в систему. Окно для задания логина и пароля представлено на рис. 21.

Рис. 21. Окно с полями для ввода логина и пароля для регистрации в системе.

После того, как логин и пароль будут заданы необходимо нажать на кнопку «Зарегистрироваться». Успешная регистрация будет сопровождаться оповещением. Окно с оповещением об успешной регистрации представлено на рис. 22.

Рис. 22. Окно с оповещением о том, что логин и пароль успешном добавлены в базу.

После завершения регистрации пользователю будет предложено авторизироваться в системе. При правильном вводе логина и пароля пользователю будет показано оповещение об успешном входе в систему. Окно авторизации и оповещение об успешном входе представлено на рис. 23.

Рис. 23. Окно для входа в приложение.

После входа в приложение пользователю будет предложено две опции: покупка тура или просмотр доступных вариантов. Сначала будет рассмотрен вариант просмотра доступных туров. Для этого необходимо нажать на кнопку «Посмотреть доступные варианты». Окно с опциями представлено на рис. 24.

Рис. 24. Окно с выбором доступных опций.

После нажатия на кнопку «Посмотреть доступные варианты» откроется окно со всеми возможными турами. Для покупки какого-либо из туров необходимо выбрать его из списка, нажать на него, после чего нажать на кнопку «Купить». Окно просмотра всех туров представлено на рис. 25.

Рис. 25. Окно с данными о всех возможных маршрутах.

После нажатия на кнопку «Купить» откроется окно с оформлением покупки тура. Окно покупки представлено на рис. 26.

Рис. 26. Окно покупки выбранного в прошлом окне тура.

После того, как будет выбран маршрут, оборудование и дата похода необходимо нажать на кнопку «Купить». После нажатия на рабочий стол будет загружен выходной документ о покупке. Окно с оповещением об успешной загрузке представлено на рис. 27.

Рис. 27. Оповещение о том, что тур был куплен и чек был загружен на рабочий стол.

Выходной документ (чек о покупке) представлен на рис. 28.

Рис. 28. Выходной документ (чек о покупке тура).

После покупки тура появляется возможность его оценить, написав отзыв в специальном поле. Окно с полем для написания отзыва представлено на рис. 29. Также на этом окне есть две кнопки: «Купить новый маршрут» и «Выход». При нажатии на вторую кнопку пользователь попадет на окно, представленное на рис. 17. При нажатии на первую кнопку попадет на окно, представленное на рис. 24. Рассмотрим вариант, когда на рис. 24 нажимается кнопка «Купить тур».

Рис. 29. Окно с возможностью оценки пройденного тура и покупки нового.

После откроется окно со списком всех маршрутов, доступного оборудования и выбором даты. После того, как будет выбран маршрут, оборудование и дата похода необходимо нажать на кнопку «Купить». После нажатия на рабочий стол будет загружен выходной документ о покупке. Окно с оповещением об успешной загрузке представлено на рис. 30.

Рис. 30. Окно покупки туров с оповещением о том, что выходной документ загружен.

Далее будет открыто окно с возможностью оценить тур после прохождения, представленное на рис. 29.

Часть инструктора.

Если в окне, представленном на рис. 17, нажать на кнопку «Инструктор» откроется окно авторизации для инструктора. Окно входа в приложение для инструктора представлено на рис. 31.

Рис. 31. Окно для входа в приложение.

После корректного ввода логина и пароля будет показано оповещение о том, что вход выполнен успешно. Окно с оповещением об успешном входе представлено на рис. 32.

Рис. 32. Окно с оповещением о том, что вход выполнен.

После входа в приложение появится рабочее окно инструктора, в котором можно: посмотреть людей, ходивших на выбранный маршрут, посмотреть статистику посещений по всем маршрутам, добавить новый маршрут, редактировать существующие маршруты, описать поврежденное оборудование. Работа всех описанных выше функций будет представлена далее. Рабочее окно инструктора представлено на рис. 33.

Рис. 33. Рабочее окно инструктора.

При выборе маршрута и нажатии на кнопку «Показать», на рабочий стол будет загружен выходной документ. Окно с оповещением о загрузке представлено на рис. 34.

Рис. 34. Окно с оповещением о том, что выходной документ был сохранен на рабочий стол.

Фрагмент выходного документа (списка людей, посещавших выбранный маршрут), представлен на рис. 35.

Рис. 35. Выходной документ со списком людей, посещавших выбранный на предыдущем окне тур.

При нажатии на кнопку «Показать», на рабочий стол будет загружен выходной документ со статистикой по посещениям. Окно с оповещением о загрузке представлено на рис. 36.

Рис. 36. Окно с оповещением о том, что выходной документ был сохранен на рабочий стол.

Выходной документ со статистикой посещения всех туров представлен на рис. 37.

Рис. 37. Выходной документ со статистикой по посещениям всех туров.

Если в окне, представленном на рис. 33, нажать на кнопку «Добавить» откроется окно с полями для ввода данных нового маршрута. Окно для добавления нового маршрута представлено на рис. 38.

Рис. 38. Окно с полями для добавления информации о новом маршруте.

Если в окне, представленном на рис. 33, нажать на кнопку «Изменить» откроется окно со списком всех маршрутов, доступных для изменения. Окно для выбора маршрута для изменения представлено на рис. 39.

Рис. 39. Окно с выбором маршрутов для изменения.

После выбора маршрута в предыдущем окне откроется окно с полями для внесения изменений в информацию о маршруте. Окно для изменения маршрута представлено на рис. 40.

Рис. 40. Окно с полями для изменения информации о выбранном в предыдущем окне маршруте.

Если во время тура было повреждено оборудование, то его можно описать. Для этого необходимо из таблицы выбрать запись аренды, где было повреждено оборудование и в специальной форме описать повреждение. После этого необходимо нажать на кнопку «Отправить описание» для сохранения его в базе данных. Оповещение о том, что описание сохранено в базе данных, представлено на рис. 41.

Рис. 41. Окно с оповещением о том, что описание поврежденного оборудования было сохранено.

Часть администратора.

Если в окне, представленном на рис. 17, нажать на кнопку «Администратор» откроется окно авторизации для администратора. Окно входа в приложение для администратора представлено на рис. 42.

Рис. 42. Окно для входа в приложение.

После корректного ввода логина и пароля будет показано оповещение о том, что вход выполнен успешно. Окно с оповещением об успешном входе представлено на рис. 43.

Рис. 43. Окно с оповещением о том, что вход выполнен.

После входа в приложение появится рабочее окно администратора, в котором можно: посмотреть финансовый отчет о продажах за выбранный период, изменить личные данные туристов и инструкторов и добавить новых инструкторов . Работа всех описанных выше функций будет представлена далее. Рабочее окно администратора представлено на рис. 44.

Рис. 44. Рабочее окно администратора.

При выборе начала и окончании периода и нажатии на кнопку «Показать» на рабочий стол будет загружен выходной документ. Окно с оповещением о загрузке документа представлено на рис. 45.

Рис. 45. Окно с оповещением о том, что выходной документ выл сохранен на рабочий стол.

Фрагмент выходного документа (финансового отчета по продажам туров) представлен на рис. 46.

Рис. 46. Фрагмент выходного документа (финансового отчета о проданных турах).

Если в окне, представленном на рис. 44, нажать на кнопку «Изменить», то откроется окно со списком данных всех туристов, доступных для изменения. Окно со списком данных туристов представлено на рис. 47.

Рис. 47. Окно с выбором туристов для изменения его личных данных.

При выборе туриста и нажатии на кнопку «Изменить» откроется окно с полями, доступными для изменения. Окно с формой для изменения данных туриста представлено на рис. 48.

Рис. 48. Окно с полями для изменения личных данных туриста, выбранного в предыдущем окне.

Если в окне, представленном на рис. 44, нажать на кнопку «Изменить», то откроется окно со списком данных всех инструкторов, доступных для изменения. Окно со списком данных инструкторов представлено на рис. 49.

Рис. 49. Окно с выбором инструктора для изменения его личных данных.

При выборе инструктора и нажатии на кнопку «Изменить» откроется окно с полями, доступными для изменения. Окно с формой для изменения данных инструктора представлено на рис. 50.

Рис. 50. Окно с полями для изменения личных данных инструктора, выбранного в предыдущем окне.

Если в окне, представленном на рис. 44, нажать на кнопку «Добавить», то откроется окно с полями для ввода информации о новом инструкторе. Окно с формой для добавления нового инструктора представлено на рис. 51.

Рис. 51. Окно с полями для ввода данных о новом инструкторе для добавления его в базу данных.

После введения всех данных о новом инструкторе необходимо нажать на кнопку «Сохранить», после чего покажется оповещение о том, что инструктор был добавлен в базу. Окно с успешным добавлением инструктора в базу представлено на рис. 52.

Рис. 52. Окно с оповещением о том, что инструктор был добавлен в базу данных.

Затем будет предложено задать инструктору логин и пароль, под которыми инструктор будет входить в приложение. После задания логина и пароля необходимо нажать на кнопку «Зарегистрировать», чтоб и эти данные были сохранены в базе. При успешном сохранении будет показано оповещение. Окно с оповещением об успешном добавлении логина и пароля в базу представлено на рис. 53.

Рис. 53. Окно с полями для ввода логина и пароля инструктора и подтверждением того, что данные были добавлены в базу.

64