Скриншот архива с проектом
Структура проекта
Задание
Разработать информационную систему для школы искусств. Приложение должно быть разработано на C# и Windows Forms с применением ООП. Приложение должно быть построено по принципу многоуровневой архитектуры - логика - интерфейс - тесты. Вам необходимо будет написать тесты. например для проверки пароля и цены курса - диапозон цен установите от 5 до 50 тысяч.
Функционал программы
- учёт студентов
- учёт администраторов
- учёт курсов
- учёт записей на курсы
- Выгрузка списка студентов, курсов, администраторов в Эксель
- Печать студентов, курсов и администраторов
- регистрация и авторизация с разделением на роли
- Модульные тесты
Дополнительно вы можете добавить - выгрузку в Эксель и печать для записей на курсы, а также добавить функционал для посещаемости курсов. Например курс по музыке был посещен 10 раз, а затем стало 8, итог - - 2. То есть принцип счетчика. Например было 8 а стало 12 - значит прирост +4.
Фрагмент программного кода (код формы Студенты)
using ArtSchool.BL.Models; using ClosedXML.Excel; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Printing; using System.Linq; using System.Windows.Forms; namespace ArtSchool.UI { public partial class StudentsForm : Form { private AppDbContext context; private List<Student> students; private PrintDocument printDocument = new PrintDocument(); private int currentRow = 0; private BindingSource studentsBindingSource = new BindingSource(); public StudentsForm() { InitializeComponent(); context = new AppDbContext(); printDocument.PrintPage += PrintDocument_PrintPage; } private void Populate() { students = context.Students.ToList(); studentsBindingSource.DataSource = new BindingList<Student>(students); StudentsDGV.DataSource = studentsBindingSource; // Скрытие ненужного столбца if (StudentsDGV.Columns.Contains("Enrollments")) { StudentsDGV.Columns["Enrollments"].Visible = false; } if (StudentsDGV.Columns.Contains("FullName")) { StudentsDGV.Columns["FullName"].Visible = false; } bindingNavigator1.BindingSource = studentsBindingSource; // Привязка к BindingNavigator } private void StudentsForm_Load(object sender, EventArgs e) { Populate(); studentsBindingSource.CurrentChanged += StudentsBindingSource_CurrentChanged; } private void StudentsBindingSource_CurrentChanged(object sender, EventArgs e) { if (studentsBindingSource.Current is Student student) { IdTb.Text = student.StudentId.ToString(); SurnameTb.Text = student.Surname; NameTb.Text = student.Name; DateofBirthTb.Text = student.DateBirth.ToString("yyyy-MM-dd"); PhoneTb.Text = student.PhoneNumber; EmailTb.Text = student.Email; } } private void AddBtn_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(IdTb.Text) || string.IsNullOrWhiteSpace(SurnameTb.Text) || string.IsNullOrWhiteSpace(NameTb.Text) || string.IsNullOrWhiteSpace(DateofBirthTb.Text) || string.IsNullOrWhiteSpace(PhoneTb.Text) || string.IsNullOrWhiteSpace(EmailTb.Text)) { MessageBox.Show("Пожалуйста, заполните все поля", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } try { var studentId = int.Parse(IdTb.Text); if (context.Students.Any(s => s.StudentId == studentId)) { MessageBox.Show("ID уже существует. Введите уникальный ID.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } var student = new Student { StudentId = studentId, Surname = SurnameTb.Text, Name = NameTb.Text, DateBirth = DateTime.Parse(DateofBirthTb.Text), PhoneNumber = PhoneTb.Text, Email = EmailTb.Text }; context.Students.Add(student); context.SaveChanges(); MessageBox.Show("Студент добавлен"); Populate(); } catch (FormatException) { MessageBox.Show("Неверный формат данных. Проверьте ID и дату.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Warning); } catch (Exception ex) { MessageBox.Show($"Ошибка при добавлении: {ex.Message}", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private void EditBtn_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(IdTb.Text)) { MessageBox.Show("Укажите ID студента для редактирования."); return; } try { int studentId = int.Parse(IdTb.Text); var student = context.Students.FirstOrDefault(s => s.StudentId == studentId); if (student == null) { MessageBox.Show("Студент не найден."); return; } student.Surname = SurnameTb.Text; student.Name = NameTb.Text; student.DateBirth = DateTime.Parse(DateofBirthTb.Text); student.PhoneNumber = PhoneTb.Text; student.Email = EmailTb.Text; context.SaveChanges(); MessageBox.Show("Данные обновлены"); Populate(); } catch (Exception ex) { MessageBox.Show("Ошибка: " + ex.Message); } } private void DeleteBtn_Click(object sender, EventArgs e) { if (string.IsNullOrWhiteSpace(IdTb.Text)) { MessageBox.Show("Укажите ID для удаления."); return; } try { int studentId = int.Parse(IdTb.Text); var student = context.Students.FirstOrDefault(s => s.StudentId == studentId); if (student != null) { context.Students.Remove(student); context.SaveChanges(); MessageBox.Show("Студент удален"); Populate(); } else { MessageBox.Show("Студент не найден."); } } catch (Exception ex) { MessageBox.Show("Ошибка: " + ex.Message); } } private void ClosedBtn_Click(object sender, EventArgs e) { Close(); } private void ExportBtn_Click(object sender, EventArgs e) { using (SaveFileDialog sfd = new SaveFileDialog() { Filter = "Excel Workbook|*.xlsx", Title = "Сохранить как Excel файл" }) { if (sfd.ShowDialog() == DialogResult.OK) { using (var workbook = new XLWorkbook()) { var worksheet = workbook.Worksheets.Add("Студенты"); // Заголовки for (int i = 0; i < StudentsDGV.Columns.Count; i++) { worksheet.Cell(1, i + 1).Value = StudentsDGV.Columns[i].HeaderText; } // Данные for (int i = 0; i < StudentsDGV.Rows.Count; i++) { for (int j = 0; j < StudentsDGV.Columns.Count; j++) { worksheet.Cell(i + 2, j + 1).Value = StudentsDGV.Rows[i].Cells[j].Value?.ToString(); } } workbook.SaveAs(sfd.FileName); MessageBox.Show("Экспорт завершён!", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information); } } } } private void PrintDocument_PrintPage(object sender, PrintPageEventArgs e) { Font font = new Font("Arial", 10); int rowHeight = 30; int x = 50; int y = 50; // Заголовки for (int i = 0; i < StudentsDGV.Columns.Count; i++) { e.Graphics.DrawString(StudentsDGV.Columns[i].HeaderText, font, Brushes.Black, x, y); x += 150; } y += rowHeight; x = 50; // Строки while (currentRow < StudentsDGV.Rows.Count) { DataGridViewRow row = StudentsDGV.Rows[currentRow]; x = 50; for (int i = 0; i < StudentsDGV.Columns.Count; i++) { string value = row.Cells[i].Value?.ToString() ?? ""; e.Graphics.DrawString(value, font, Brushes.Black, x, y); x += 150; } y += rowHeight; currentRow++; if (y > e.MarginBounds.Bottom) { e.HasMorePages = true; return; } } // Последняя страница e.HasMorePages = false; currentRow = 0; } private void PrintBtn_Click(object sender, EventArgs e) { using (PrintDialog printDialog = new PrintDialog()) { printDialog.Document = printDocument; if (printDialog.ShowDialog() == DialogResult.OK) { printDocument.Print(); } } } private void StudentsDGV_CellClick(object sender, DataGridViewCellEventArgs e) { if (StudentsDGV.SelectedRows.Count > 0) { var row = StudentsDGV.SelectedRows[0]; IdTb.Text = row.Cells["StudentId"].Value?.ToString(); SurnameTb.Text = row.Cells["Surname"].Value?.ToString(); NameTb.Text = row.Cells["Name"].Value?.ToString(); DateofBirthTb.Text = row.Cells["DateBirth"].Value?.ToString(); PhoneTb.Text = row.Cells["PhoneNumber"].Value?.ToString(); EmailTb.Text = row.Cells["Email"].Value?.ToString(); } } private void RecordsViewsBtn_Click(object sender, EventArgs e) { EnrollmentForm enrollmentForm = new EnrollmentForm(); enrollmentForm.ShowDialog(); } } }
Фрагмент программного кода (код модульного теста )
using ArtSchool.BL.Helpers; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace ArtSchool.UnitTests { [TestClass] public class SecurityHelperTests { [TestMethod] public void TestHashPassword() { // Arrange string password = "123456"; string expectedHash = SecurityHelper.HashPassword(password); // Замените на реальный хэш // Act string actualHash = SecurityHelper.HashPassword(password); // Assert Assert.AreEqual(expectedHash, actualHash); } [TestMethod] public void TestVerifyPassword() { // Arrange string password = "123456"; string hashedPassword = SecurityHelper.HashPassword(password); // Act bool isValid = SecurityHelper.VerifyPassword(password, hashedPassword); // Assert Assert.IsTrue(isValid); } [TestMethod] public void TestVerifyPasswordWithInvalidPassword() { // Arrange string password = "123456"; string invalidPassword = "wrongpassword"; string hashedPassword = SecurityHelper.HashPassword(password); // Act bool isValid = SecurityHelper.VerifyPassword(invalidPassword, hashedPassword); // Assert Assert.IsFalse(isValid); } } }
Пояснения по запуску программы
Для эффективной работы с приложением смотри приложенную инструкцию. Следуйте описанию в инструкции и у вас все получится. Приятного пользования.
-