using System; using System.Data; using System.Windows; using Npgsql; namespace ych { public partial class MainWindow : Window { private readonly string _connectionString = "Host=edu-pg.itiscaf.ru;Port=5432;Database=dbwork;" + "Username=gaukov_dp;Password=4K62ebY72%h;"; private readonly string _userRole; private string _currentTable = ""; private DataTable _dataTable = new DataTable(); public MainWindow(string userRole) { InitializeComponent(); _userRole = userRole; ApplySecurity(); } private void ApplySecurity() { if (_userRole == "admin") { RoleLabel.Text = "Роль: Администратор"; } else if (_userRole == "teacher") { RoleLabel.Text = "Роль: Преподаватель"; BtnDelete.IsEnabled = false; BtnDelete.Opacity = 0.4; } else if (_userRole == "student") { RoleLabel.Text = "Роль: Студент"; BtnAdd.Visibility = Visibility.Collapsed; BtnDelete.Visibility = Visibility.Collapsed; BtnStudents.Visibility = Visibility.Collapsed; BtnTeachers.Visibility = Visibility.Collapsed; BtnGroups.Visibility = Visibility.Collapsed; } } private void LoadTable(string table, string title, string query = "") { _currentTable = table; TitleText.Text = title; bool isTable = string.IsNullOrEmpty(query); bool canEdit = _userRole == "admin" || _userRole == "teacher"; ActionPanel.Visibility = (isTable && canEdit) ? Visibility.Visible : Visibility.Collapsed; string sql = isTable ? string.Format("SELECT * FROM {0} ORDER BY 1", table) : query; try { using (var conn = new NpgsqlConnection(_connectionString)) { conn.Open(); using (var adapter = new NpgsqlDataAdapter(sql, conn)) { _dataTable = new DataTable(); adapter.Fill(_dataTable); MainGrid.IsReadOnly = (_userRole == "student" || !isTable); MainGrid.ItemsSource = _dataTable.DefaultView; SetStatus(string.Format("Загружено строк: {0}", _dataTable.Rows.Count)); } } } catch (Exception ex) { ShowError(ex.Message); } } private void ShowStudents(object s, RoutedEventArgs e) { LoadTable("students", "Студенты"); } private void ShowSubjects(object s, RoutedEventArgs e) { LoadTable("subjects", "Предметы"); } private void ShowTeachers(object s, RoutedEventArgs e) { LoadTable("teachers", "Преподаватели"); } private void ShowGroups(object s, RoutedEventArgs e) { LoadTable("groups", "Группы"); } private void ShowGrades(object s, RoutedEventArgs e) { LoadTable("grades", "Оценки"); } private void ShowFailing(object s, RoutedEventArgs e) { LoadTable("", "Неуспевающие студенты", @" SELECT s.last_name AS фамилия, s.first_name AS имя, gr.id AS группа, sub.title AS предмет, g.grade AS оценка FROM grades g JOIN students s ON g.record_book_id = s.record_book_id JOIN groups gr ON s.group_id = gr.id JOIN subjects sub ON g.subject_id = sub.id WHERE g.grade = 2 ORDER BY sub.title, s.last_name"); } private void ShowAvg(object s, RoutedEventArgs e) { LoadTable("", "Средний балл по студентам", @" SELECT s.last_name AS фамилия, s.first_name AS имя, ROUND(AVG(g.grade::NUMERIC), 2) AS средний_балл FROM grades g JOIN students s ON g.record_book_id = s.record_book_id GROUP BY s.record_book_id, s.last_name, s.first_name ORDER BY средний_балл DESC"); } private void AddRow(object s, RoutedEventArgs e) { if (string.IsNullOrEmpty(_currentTable)) return; _dataTable.Rows.Add(_dataTable.NewRow()); MainGrid.ScrollIntoView(MainGrid.Items[MainGrid.Items.Count - 1]); SetStatus("Заполните новую строку и нажмите Сохранить"); } private void SaveRow(object s, RoutedEventArgs e) { if (string.IsNullOrEmpty(_currentTable)) return; // 1. Проверяем, есть ли пустые строки foreach (DataRow row in _dataTable.Rows) { // RowState.Added означает, что строка новая и еще не сохранена if (row.RowState == DataRowState.Added) { bool isEmpty = true; // Проходим по всем колонкам строки foreach (DataColumn col in _dataTable.Columns) { // Если хоть одно поле не пустое и не DBNull - строка заполнена if (row[col] != DBNull.Value && !string.IsNullOrEmpty(row[col].ToString())) { isEmpty = false; break; } } // Если строка пустая - удаляем её, чтобы не вызывать ошибку БД if (isEmpty) { row.Delete(); } } } // Если после чистки ничего не осталось для сохранения - выходим if (_dataTable.GetChanges() == null) { SetStatus("Пустые строки удалены. Заполните данные."); return; } try { using (var conn = new NpgsqlConnection(_connectionString)) { conn.Open(); using (var adapter = new NpgsqlDataAdapter( $"SELECT * FROM gaukov_dp.{_currentTable} WHERE 1=0", conn)) { using (var builder = new NpgsqlCommandBuilder(adapter)) { adapter.Update(_dataTable); _dataTable.AcceptChanges(); SetStatus("Данные успешно сохранены"); LoadTable(_currentTable, TitleText.Text); } } } } catch (Exception ex) { ShowError(ex.Message); } } private void DeleteRow(object s, RoutedEventArgs e) { if (_userRole != "admin") { ShowError("Недостаточно прав для удаления"); return; } if (!(MainGrid.SelectedItem is DataRowView row)) return; var result = MessageBox.Show( "Удалить выбранную запись? (Все связанные оценки тоже будут удалены)", "Подтверждение", MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result != MessageBoxResult.Yes) return; try { // Получаем ID студента (предполагаем, что это первая колонка или record_book_id) // Тебе нужно знать точное имя колонки ID в таблице students var studentId = row["record_book_id"]; // Или row["id"], посмотри в таблице using (var conn = new NpgsqlConnection(_connectionString)) { conn.Open(); using (var transaction = conn.BeginTransaction()) { try { // 1. Сначала удаляем оценки студента string deleteGradesSql = "DELETE FROM gaukov_dp.grades WHERE record_book_id = @id"; using (var cmd = new NpgsqlCommand(deleteGradesSql, conn, transaction)) { cmd.Parameters.AddWithValue("id", studentId); cmd.ExecuteNonQuery(); } // 2. Теперь удаляем самого студента через DataTable row.Row.Delete(); using (var adapter = new NpgsqlDataAdapter( $"SELECT * FROM gaukov_dp.{_currentTable} WHERE 1=0", conn)) { adapter.SelectCommand.Transaction = transaction; using (var builder = new NpgsqlCommandBuilder(adapter)) { adapter.Update(_dataTable); } } transaction.Commit(); _dataTable.AcceptChanges(); SetStatus("Запись и связанные данные удалены"); } catch { transaction.Rollback(); throw; } } } } catch (Exception ex) { row.Row.RejectChanges(); ShowError(ex.Message); } } private void Logout_Click(object s, RoutedEventArgs e) { var login = new LoginWindow(); login.Show(); Close(); } private void SetStatus(string msg) { StatusText.Text = msg; } private void ShowError(string msg) { StatusText.Text = string.Format("Ошибка: {0}", msg); MessageBox.Show(msg, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error); } } }