930 lines
38 KiB
C#
930 lines
38 KiB
C#
![]() |
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.Data.SQLite;
|
|||
|
using System.Configuration;
|
|||
|
using System.IO;
|
|||
|
|
|||
|
namespace WindowsFormsApp1
|
|||
|
{
|
|||
|
public partial class Form1 : Form
|
|||
|
{
|
|||
|
// Путь к файлу SQLite
|
|||
|
private string connectionString = @"Data Source=EmployeeDB.db;Version=3;";
|
|||
|
|
|||
|
public Form1()
|
|||
|
{
|
|||
|
InitializeComponent();
|
|||
|
this.AcceptButton = buttonLogin;
|
|||
|
this.Text = "Авторизация";
|
|||
|
this.FormBorderStyle = FormBorderStyle.FixedDialog;
|
|||
|
this.MaximizeBox = false;
|
|||
|
this.StartPosition = FormStartPosition.CenterScreen;
|
|||
|
|
|||
|
// Добавляем компоненты
|
|||
|
InitializeLoginComponents();
|
|||
|
|
|||
|
// Создаем базу данных, если она не существует
|
|||
|
CreateDatabaseIfNotExists();
|
|||
|
}
|
|||
|
|
|||
|
private void CreateDatabaseIfNotExists()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (!File.Exists("EmployeeDB.db"))
|
|||
|
{
|
|||
|
SQLiteConnection.CreateFile("EmployeeDB.db");
|
|||
|
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
|
|||
|
{
|
|||
|
connection.Open();
|
|||
|
|
|||
|
// Создаем таблицу пользователей
|
|||
|
string createUsersTable = @"CREATE TABLE IF NOT EXISTS Users (
|
|||
|
UserID INTEGER PRIMARY KEY AUTOINCREMENT,
|
|||
|
Login TEXT NOT NULL,
|
|||
|
Password TEXT NOT NULL)";
|
|||
|
using (SQLiteCommand command = new SQLiteCommand(createUsersTable, connection))
|
|||
|
{
|
|||
|
command.ExecuteNonQuery();
|
|||
|
}
|
|||
|
|
|||
|
// Создаем admin пользователя
|
|||
|
string insertAdmin = @"INSERT INTO Users (Login, Password) VALUES ('admin', 'admin')";
|
|||
|
using (SQLiteCommand command = new SQLiteCommand(insertAdmin, connection))
|
|||
|
{
|
|||
|
command.ExecuteNonQuery();
|
|||
|
}
|
|||
|
|
|||
|
// Создаем таблицу сотрудников
|
|||
|
string createEmployeesTable = @"CREATE TABLE IF NOT EXISTS Employees (
|
|||
|
EmployeeID INTEGER PRIMARY KEY AUTOINCREMENT,
|
|||
|
LastName TEXT NOT NULL,
|
|||
|
FirstName TEXT NOT NULL,
|
|||
|
MiddleName TEXT,
|
|||
|
Position TEXT,
|
|||
|
Department TEXT)";
|
|||
|
using (SQLiteCommand command = new SQLiteCommand(createEmployeesTable, connection))
|
|||
|
{
|
|||
|
command.ExecuteNonQuery();
|
|||
|
}
|
|||
|
|
|||
|
// Создаем таблицу посещаемости
|
|||
|
string createAttendanceTable = @"CREATE TABLE IF NOT EXISTS Attendance (
|
|||
|
AttendanceID INTEGER PRIMARY KEY AUTOINCREMENT,
|
|||
|
EmployeeID INTEGER NOT NULL,
|
|||
|
ArrivalTime TEXT NOT NULL,
|
|||
|
DepartureTime TEXT,
|
|||
|
FOREIGN KEY (EmployeeID) REFERENCES Employees(EmployeeID))";
|
|||
|
using (SQLiteCommand command = new SQLiteCommand(createAttendanceTable, connection))
|
|||
|
{
|
|||
|
command.ExecuteNonQuery();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
MessageBox.Show("Ошибка инициализации базы данных: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void InitializeLoginComponents()
|
|||
|
{
|
|||
|
// Заголовок
|
|||
|
Label lblHeader = new Label
|
|||
|
{
|
|||
|
Text = "Вход в систему учета посещаемости",
|
|||
|
Font = new Font("Arial", 14, FontStyle.Bold),
|
|||
|
Width = 350,
|
|||
|
TextAlign = ContentAlignment.MiddleCenter,
|
|||
|
Location = new Point(70, 20)
|
|||
|
};
|
|||
|
|
|||
|
// Поле логина
|
|||
|
Label lblLogin = new Label
|
|||
|
{
|
|||
|
Text = "Логин:",
|
|||
|
Location = new Point(70, 70),
|
|||
|
Width = 100
|
|||
|
};
|
|||
|
|
|||
|
TextBox txtLogin = new TextBox
|
|||
|
{
|
|||
|
Name = "txtLogin",
|
|||
|
Location = new Point(170, 70),
|
|||
|
Width = 200
|
|||
|
};
|
|||
|
|
|||
|
// Поле пароля
|
|||
|
Label lblPassword = new Label
|
|||
|
{
|
|||
|
Text = "Пароль:",
|
|||
|
Location = new Point(70, 100),
|
|||
|
Width = 100
|
|||
|
};
|
|||
|
|
|||
|
TextBox txtPassword = new TextBox
|
|||
|
{
|
|||
|
Name = "txtPassword",
|
|||
|
Location = new Point(170, 100),
|
|||
|
Width = 200,
|
|||
|
PasswordChar = '*'
|
|||
|
};
|
|||
|
|
|||
|
// Кнопка входа
|
|||
|
Button buttonLogin = new Button
|
|||
|
{
|
|||
|
Name = "buttonLogin",
|
|||
|
Text = "Войти",
|
|||
|
Location = new Point(200, 150),
|
|||
|
Width = 100
|
|||
|
};
|
|||
|
buttonLogin.Click += ButtonLogin_Click;
|
|||
|
|
|||
|
// Добавляем все компоненты на форму
|
|||
|
this.Controls.Add(lblHeader);
|
|||
|
this.Controls.Add(lblLogin);
|
|||
|
this.Controls.Add(txtLogin);
|
|||
|
this.Controls.Add(lblPassword);
|
|||
|
this.Controls.Add(txtPassword);
|
|||
|
this.Controls.Add(buttonLogin);
|
|||
|
|
|||
|
// Устанавливаем размеры формы
|
|||
|
this.Width = 480;
|
|||
|
this.Height = 250;
|
|||
|
}
|
|||
|
|
|||
|
private void ButtonLogin_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
string login = this.Controls["txtLogin"].Text;
|
|||
|
string password = this.Controls["txtPassword"].Text;
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
|
|||
|
{
|
|||
|
connection.Open();
|
|||
|
string query = "SELECT COUNT(*) FROM Users WHERE Login = @Login AND Password = @Password";
|
|||
|
using (SQLiteCommand command = new SQLiteCommand(query, connection))
|
|||
|
{
|
|||
|
command.Parameters.AddWithValue("@Login", login);
|
|||
|
command.Parameters.AddWithValue("@Password", password);
|
|||
|
int count = Convert.ToInt32(command.ExecuteScalar());
|
|||
|
|
|||
|
if (count > 0)
|
|||
|
{
|
|||
|
MessageBox.Show("Вход выполнен успешно!", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|||
|
|
|||
|
// Скрываем текущую форму
|
|||
|
this.Hide();
|
|||
|
|
|||
|
// Открываем главную форму приложения
|
|||
|
MainForm mainForm = new MainForm(connectionString);
|
|||
|
mainForm.FormClosed += (s, args) => this.Close();
|
|||
|
mainForm.Show();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
MessageBox.Show("Неверный логин или пароль!", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
MessageBox.Show("Ошибка входа: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Форма для работы с таблицами
|
|||
|
public class MainForm : Form
|
|||
|
{
|
|||
|
private string connectionString;
|
|||
|
private TabControl tabControl;
|
|||
|
private TabPage tabEmployees;
|
|||
|
private TabPage tabAttendance;
|
|||
|
private DataGridView dgvEmployees;
|
|||
|
private DataGridView dgvAttendance;
|
|||
|
|
|||
|
public MainForm(string connString)
|
|||
|
{
|
|||
|
connectionString = connString;
|
|||
|
|
|||
|
InitializeComponent();
|
|||
|
LoadEmployeeData();
|
|||
|
LoadAttendanceData();
|
|||
|
}
|
|||
|
|
|||
|
private void InitializeComponent()
|
|||
|
{
|
|||
|
this.Text = "Система учета посещаемости";
|
|||
|
this.Width = 800;
|
|||
|
this.Height = 600;
|
|||
|
this.StartPosition = FormStartPosition.CenterScreen;
|
|||
|
|
|||
|
// Создаем вкладки
|
|||
|
tabControl = new TabControl
|
|||
|
{
|
|||
|
Dock = DockStyle.Fill
|
|||
|
};
|
|||
|
|
|||
|
// Вкладка "Сотрудники"
|
|||
|
tabEmployees = new TabPage
|
|||
|
{
|
|||
|
Text = "Сотрудники"
|
|||
|
};
|
|||
|
|
|||
|
// Вкладка "Посещаемость"
|
|||
|
tabAttendance = new TabPage
|
|||
|
{
|
|||
|
Text = "Посещаемость"
|
|||
|
};
|
|||
|
|
|||
|
// Панель для кнопок сотрудников
|
|||
|
Panel panelEmployeesButtons = new Panel
|
|||
|
{
|
|||
|
Dock = DockStyle.Top,
|
|||
|
Height = 50
|
|||
|
};
|
|||
|
|
|||
|
// Кнопки для управления сотрудниками
|
|||
|
Button btnAddEmployee = new Button
|
|||
|
{
|
|||
|
Text = "Добавить сотрудника",
|
|||
|
Width = 150,
|
|||
|
Location = new Point(10, 10)
|
|||
|
};
|
|||
|
btnAddEmployee.Click += BtnAddEmployee_Click;
|
|||
|
|
|||
|
Button btnEditEmployee = new Button
|
|||
|
{
|
|||
|
Text = "Редактировать",
|
|||
|
Width = 150,
|
|||
|
Location = new Point(170, 10)
|
|||
|
};
|
|||
|
btnEditEmployee.Click += BtnEditEmployee_Click;
|
|||
|
|
|||
|
Button btnDeleteEmployee = new Button
|
|||
|
{
|
|||
|
Text = "Удалить",
|
|||
|
Width = 150,
|
|||
|
Location = new Point(330, 10)
|
|||
|
};
|
|||
|
btnDeleteEmployee.Click += BtnDeleteEmployee_Click;
|
|||
|
|
|||
|
// Добавляем кнопки на панель
|
|||
|
panelEmployeesButtons.Controls.Add(btnAddEmployee);
|
|||
|
panelEmployeesButtons.Controls.Add(btnEditEmployee);
|
|||
|
panelEmployeesButtons.Controls.Add(btnDeleteEmployee);
|
|||
|
|
|||
|
// Таблица для сотрудников
|
|||
|
dgvEmployees = new DataGridView
|
|||
|
{
|
|||
|
AllowUserToAddRows = false,
|
|||
|
AllowUserToDeleteRows = false,
|
|||
|
ReadOnly = true,
|
|||
|
AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill,
|
|||
|
SelectionMode = DataGridViewSelectionMode.FullRowSelect,
|
|||
|
Dock = DockStyle.Fill
|
|||
|
};
|
|||
|
|
|||
|
// ВАЖНО: сначала добавляем DataGridView, затем панель кнопок
|
|||
|
// Это обеспечивает правильное расположение элементов сверху вниз
|
|||
|
tabEmployees.Controls.Add(dgvEmployees);
|
|||
|
tabEmployees.Controls.Add(panelEmployeesButtons);
|
|||
|
|
|||
|
// Панель для кнопок посещаемости
|
|||
|
Panel panelAttendanceButtons = new Panel
|
|||
|
{
|
|||
|
Dock = DockStyle.Top,
|
|||
|
Height = 50
|
|||
|
};
|
|||
|
|
|||
|
// Кнопки для управления посещаемостью
|
|||
|
Button btnArrival = new Button
|
|||
|
{
|
|||
|
Text = "Отметить прибытие",
|
|||
|
Width = 150,
|
|||
|
Location = new Point(10, 10)
|
|||
|
};
|
|||
|
btnArrival.Click += BtnArrival_Click;
|
|||
|
|
|||
|
Button btnDeparture = new Button
|
|||
|
{
|
|||
|
Text = "Отметить убытие",
|
|||
|
Width = 150,
|
|||
|
Location = new Point(170, 10)
|
|||
|
};
|
|||
|
btnDeparture.Click += BtnDeparture_Click;
|
|||
|
|
|||
|
// Добавляем кнопки на панель
|
|||
|
panelAttendanceButtons.Controls.Add(btnArrival);
|
|||
|
panelAttendanceButtons.Controls.Add(btnDeparture);
|
|||
|
|
|||
|
// Таблица для посещаемости
|
|||
|
dgvAttendance = new DataGridView
|
|||
|
{
|
|||
|
AllowUserToAddRows = false,
|
|||
|
AllowUserToDeleteRows = false,
|
|||
|
ReadOnly = true,
|
|||
|
AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill,
|
|||
|
SelectionMode = DataGridViewSelectionMode.FullRowSelect,
|
|||
|
Dock = DockStyle.Fill
|
|||
|
};
|
|||
|
|
|||
|
// ВАЖНО: сначала добавляем DataGridView, затем панель кнопок
|
|||
|
tabAttendance.Controls.Add(dgvAttendance);
|
|||
|
tabAttendance.Controls.Add(panelAttendanceButtons);
|
|||
|
|
|||
|
// Добавляем вкладки в контрол
|
|||
|
tabControl.TabPages.Add(tabEmployees);
|
|||
|
tabControl.TabPages.Add(tabAttendance);
|
|||
|
|
|||
|
// Добавляем контрол вкладок на форму
|
|||
|
this.Controls.Add(tabControl);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
private void LoadEmployeeData()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
|
|||
|
{
|
|||
|
connection.Open();
|
|||
|
string query = "SELECT EmployeeID, LastName, FirstName, MiddleName, Position, Department FROM Employees";
|
|||
|
SQLiteDataAdapter adapter = new SQLiteDataAdapter(query, connection);
|
|||
|
DataTable dt = new DataTable();
|
|||
|
adapter.Fill(dt);
|
|||
|
dgvEmployees.DataSource = dt;
|
|||
|
|
|||
|
// Переименовываем колонки для отображения
|
|||
|
if (dt.Rows.Count > 0)
|
|||
|
{
|
|||
|
dgvEmployees.Columns["EmployeeID"].HeaderText = "ID";
|
|||
|
dgvEmployees.Columns["LastName"].HeaderText = "Фамилия";
|
|||
|
dgvEmployees.Columns["FirstName"].HeaderText = "Имя";
|
|||
|
dgvEmployees.Columns["MiddleName"].HeaderText = "Отчество";
|
|||
|
dgvEmployees.Columns["Position"].HeaderText = "Должность";
|
|||
|
dgvEmployees.Columns["Department"].HeaderText = "Отдел";
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
MessageBox.Show("Ошибка загрузки данных сотрудников: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void LoadAttendanceData()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
|
|||
|
{
|
|||
|
connection.Open();
|
|||
|
// Изменен синтаксис конкатенации для SQLite
|
|||
|
string query = @"SELECT a.AttendanceID, e.EmployeeID,
|
|||
|
e.LastName || ' ' || e.FirstName || ' ' || COALESCE(e.MiddleName, '') as FullName,
|
|||
|
a.ArrivalTime, a.DepartureTime
|
|||
|
FROM Attendance a
|
|||
|
JOIN Employees e ON a.EmployeeID = e.EmployeeID
|
|||
|
ORDER BY a.ArrivalTime DESC";
|
|||
|
SQLiteDataAdapter adapter = new SQLiteDataAdapter(query, connection);
|
|||
|
DataTable dt = new DataTable();
|
|||
|
adapter.Fill(dt);
|
|||
|
dgvAttendance.DataSource = dt;
|
|||
|
|
|||
|
// Переименовываем колонки для отображения
|
|||
|
if (dt.Rows.Count > 0)
|
|||
|
{
|
|||
|
dgvAttendance.Columns["AttendanceID"].HeaderText = "ID записи";
|
|||
|
dgvAttendance.Columns["EmployeeID"].HeaderText = "ID сотрудника";
|
|||
|
dgvAttendance.Columns["FullName"].HeaderText = "ФИО";
|
|||
|
dgvAttendance.Columns["ArrivalTime"].HeaderText = "Время прибытия";
|
|||
|
dgvAttendance.Columns["DepartureTime"].HeaderText = "Время убытия";
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
MessageBox.Show("Ошибка загрузки данных посещаемости: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Обработчики событий для кнопок
|
|||
|
private void BtnAddEmployee_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
EmployeeForm form = new EmployeeForm(connectionString, 0);
|
|||
|
if (form.ShowDialog() == DialogResult.OK)
|
|||
|
{
|
|||
|
LoadEmployeeData();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void BtnEditEmployee_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if (dgvEmployees.SelectedRows.Count > 0)
|
|||
|
{
|
|||
|
int employeeId = Convert.ToInt32(dgvEmployees.SelectedRows[0].Cells["EmployeeID"].Value);
|
|||
|
EmployeeForm form = new EmployeeForm(connectionString, employeeId);
|
|||
|
if (form.ShowDialog() == DialogResult.OK)
|
|||
|
{
|
|||
|
LoadEmployeeData();
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
MessageBox.Show("Выберите сотрудника для редактирования", "Информация", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void BtnDeleteEmployee_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if (dgvEmployees.SelectedRows.Count > 0)
|
|||
|
{
|
|||
|
int employeeId = Convert.ToInt32(dgvEmployees.SelectedRows[0].Cells["EmployeeID"].Value);
|
|||
|
string employeeName = dgvEmployees.SelectedRows[0].Cells["LastName"].Value.ToString() + " " +
|
|||
|
dgvEmployees.SelectedRows[0].Cells["FirstName"].Value.ToString();
|
|||
|
|
|||
|
DialogResult result = MessageBox.Show($"Вы уверены, что хотите удалить сотрудника {employeeName}?",
|
|||
|
"Подтверждение", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
|||
|
if (result == DialogResult.Yes)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
|
|||
|
{
|
|||
|
connection.Open();
|
|||
|
// Начинаем транзакцию
|
|||
|
using (SQLiteTransaction transaction = connection.BeginTransaction())
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
// Сначала удаляем записи посещаемости
|
|||
|
string deleteAttendance = "DELETE FROM Attendance WHERE EmployeeID = @EmployeeID";
|
|||
|
using (SQLiteCommand command = new SQLiteCommand(deleteAttendance, connection, transaction))
|
|||
|
{
|
|||
|
command.Parameters.AddWithValue("@EmployeeID", employeeId);
|
|||
|
command.ExecuteNonQuery();
|
|||
|
}
|
|||
|
|
|||
|
// Затем удаляем сотрудника
|
|||
|
string deleteEmployee = "DELETE FROM Employees WHERE EmployeeID = @EmployeeID";
|
|||
|
using (SQLiteCommand command = new SQLiteCommand(deleteEmployee, connection, transaction))
|
|||
|
{
|
|||
|
command.Parameters.AddWithValue("@EmployeeID", employeeId);
|
|||
|
command.ExecuteNonQuery();
|
|||
|
}
|
|||
|
|
|||
|
// Фиксируем изменения
|
|||
|
transaction.Commit();
|
|||
|
MessageBox.Show("Сотрудник успешно удален", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|||
|
LoadEmployeeData();
|
|||
|
LoadAttendanceData();
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
// Откатываем изменения при ошибке
|
|||
|
transaction.Rollback();
|
|||
|
throw ex;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
MessageBox.Show("Ошибка при удалении сотрудника: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
MessageBox.Show("Выберите сотрудника для удаления", "Информация", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void BtnArrival_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
AttendanceForm form = new AttendanceForm(connectionString, true);
|
|||
|
if (form.ShowDialog() == DialogResult.OK)
|
|||
|
{
|
|||
|
LoadAttendanceData();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void BtnDeparture_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
AttendanceForm form = new AttendanceForm(connectionString, false);
|
|||
|
if (form.ShowDialog() == DialogResult.OK)
|
|||
|
{
|
|||
|
LoadAttendanceData();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Форма для добавления/редактирования сотрудника
|
|||
|
public class EmployeeForm : Form
|
|||
|
{
|
|||
|
private string connectionString;
|
|||
|
private int employeeId;
|
|||
|
private TextBox txtLastName;
|
|||
|
private TextBox txtFirstName;
|
|||
|
private TextBox txtMiddleName;
|
|||
|
private TextBox txtPosition;
|
|||
|
private TextBox txtDepartment;
|
|||
|
|
|||
|
public EmployeeForm(string connString, int id)
|
|||
|
{
|
|||
|
connectionString = connString;
|
|||
|
employeeId = id;
|
|||
|
|
|||
|
InitializeComponent();
|
|||
|
|
|||
|
if (employeeId > 0)
|
|||
|
{
|
|||
|
this.Text = "Редактирование сотрудника";
|
|||
|
LoadEmployeeData();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
this.Text = "Добавление нового сотрудника";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void InitializeComponent()
|
|||
|
{
|
|||
|
this.Width = 400;
|
|||
|
this.Height = 300;
|
|||
|
this.StartPosition = FormStartPosition.CenterParent;
|
|||
|
this.FormBorderStyle = FormBorderStyle.FixedDialog;
|
|||
|
this.MaximizeBox = false;
|
|||
|
this.MinimizeBox = false;
|
|||
|
|
|||
|
// Поля для ввода данных
|
|||
|
Label lblLastName = new Label
|
|||
|
{
|
|||
|
Text = "Фамилия:",
|
|||
|
Location = new Point(30, 20),
|
|||
|
Width = 100
|
|||
|
};
|
|||
|
|
|||
|
txtLastName = new TextBox
|
|||
|
{
|
|||
|
Location = new Point(150, 20),
|
|||
|
Width = 200
|
|||
|
};
|
|||
|
|
|||
|
Label lblFirstName = new Label
|
|||
|
{
|
|||
|
Text = "Имя:",
|
|||
|
Location = new Point(30, 50),
|
|||
|
Width = 100
|
|||
|
};
|
|||
|
|
|||
|
txtFirstName = new TextBox
|
|||
|
{
|
|||
|
Location = new Point(150, 50),
|
|||
|
Width = 200
|
|||
|
};
|
|||
|
|
|||
|
Label lblMiddleName = new Label
|
|||
|
{
|
|||
|
Text = "Отчество:",
|
|||
|
Location = new Point(30, 80),
|
|||
|
Width = 100
|
|||
|
};
|
|||
|
|
|||
|
txtMiddleName = new TextBox
|
|||
|
{
|
|||
|
Location = new Point(150, 80),
|
|||
|
Width = 200
|
|||
|
};
|
|||
|
|
|||
|
Label lblPosition = new Label
|
|||
|
{
|
|||
|
Text = "Должность:",
|
|||
|
Location = new Point(30, 110),
|
|||
|
Width = 100
|
|||
|
};
|
|||
|
|
|||
|
txtPosition = new TextBox
|
|||
|
{
|
|||
|
Location = new Point(150, 110),
|
|||
|
Width = 200
|
|||
|
};
|
|||
|
|
|||
|
Label lblDepartment = new Label
|
|||
|
{
|
|||
|
Text = "Отдел:",
|
|||
|
Location = new Point(30, 140),
|
|||
|
Width = 100
|
|||
|
};
|
|||
|
|
|||
|
txtDepartment = new TextBox
|
|||
|
{
|
|||
|
Location = new Point(150, 140),
|
|||
|
Width = 200
|
|||
|
};
|
|||
|
|
|||
|
// Кнопки
|
|||
|
Button btnSave = new Button
|
|||
|
{
|
|||
|
Text = "Сохранить",
|
|||
|
DialogResult = DialogResult.OK,
|
|||
|
Location = new Point(150, 180),
|
|||
|
Width = 100
|
|||
|
};
|
|||
|
btnSave.Click += BtnSave_Click;
|
|||
|
|
|||
|
Button btnCancel = new Button
|
|||
|
{
|
|||
|
Text = "Отмена",
|
|||
|
DialogResult = DialogResult.Cancel,
|
|||
|
Location = new Point(260, 180),
|
|||
|
Width = 100
|
|||
|
};
|
|||
|
|
|||
|
// Добавляем компоненты на форму
|
|||
|
this.Controls.Add(lblLastName);
|
|||
|
this.Controls.Add(txtLastName);
|
|||
|
this.Controls.Add(lblFirstName);
|
|||
|
this.Controls.Add(txtFirstName);
|
|||
|
this.Controls.Add(lblMiddleName);
|
|||
|
this.Controls.Add(txtMiddleName);
|
|||
|
this.Controls.Add(lblPosition);
|
|||
|
this.Controls.Add(txtPosition);
|
|||
|
this.Controls.Add(lblDepartment);
|
|||
|
this.Controls.Add(txtDepartment);
|
|||
|
this.Controls.Add(btnSave);
|
|||
|
this.Controls.Add(btnCancel);
|
|||
|
|
|||
|
this.AcceptButton = btnSave;
|
|||
|
this.CancelButton = btnCancel;
|
|||
|
}
|
|||
|
|
|||
|
private void LoadEmployeeData()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
|
|||
|
{
|
|||
|
connection.Open();
|
|||
|
string query = "SELECT LastName, FirstName, MiddleName, Position, Department FROM Employees WHERE EmployeeID = @EmployeeID";
|
|||
|
using (SQLiteCommand command = new SQLiteCommand(query, connection))
|
|||
|
{
|
|||
|
command.Parameters.AddWithValue("@EmployeeID", employeeId);
|
|||
|
using (SQLiteDataReader reader = command.ExecuteReader())
|
|||
|
{
|
|||
|
if (reader.Read())
|
|||
|
{
|
|||
|
txtLastName.Text = reader["LastName"].ToString();
|
|||
|
txtFirstName.Text = reader["FirstName"].ToString();
|
|||
|
txtMiddleName.Text = reader["MiddleName"].ToString();
|
|||
|
txtPosition.Text = reader["Position"].ToString();
|
|||
|
txtDepartment.Text = reader["Department"].ToString();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
MessageBox.Show("Ошибка при загрузке данных сотрудника: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void BtnSave_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if (string.IsNullOrWhiteSpace(txtLastName.Text) || string.IsNullOrWhiteSpace(txtFirstName.Text))
|
|||
|
{
|
|||
|
MessageBox.Show("Фамилия и имя обязательны для заполнения", "Предупреждение", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|||
|
this.DialogResult = DialogResult.None;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
|
|||
|
{
|
|||
|
connection.Open();
|
|||
|
string query;
|
|||
|
|
|||
|
if (employeeId > 0)
|
|||
|
{
|
|||
|
// Обновление существующего сотрудника
|
|||
|
query = @"UPDATE Employees SET
|
|||
|
LastName = @LastName,
|
|||
|
FirstName = @FirstName,
|
|||
|
MiddleName = @MiddleName,
|
|||
|
Position = @Position,
|
|||
|
Department = @Department
|
|||
|
WHERE EmployeeID = @EmployeeID";
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// Добавление нового сотрудника
|
|||
|
query = @"INSERT INTO Employees (LastName, FirstName, MiddleName, Position, Department)
|
|||
|
VALUES (@LastName, @FirstName, @MiddleName, @Position, @Department)";
|
|||
|
}
|
|||
|
|
|||
|
using (SQLiteCommand command = new SQLiteCommand(query, connection))
|
|||
|
{
|
|||
|
command.Parameters.AddWithValue("@LastName", txtLastName.Text);
|
|||
|
command.Parameters.AddWithValue("@FirstName", txtFirstName.Text);
|
|||
|
command.Parameters.AddWithValue("@MiddleName", txtMiddleName.Text);
|
|||
|
command.Parameters.AddWithValue("@Position", txtPosition.Text);
|
|||
|
command.Parameters.AddWithValue("@Department", txtDepartment.Text);
|
|||
|
|
|||
|
if (employeeId > 0)
|
|||
|
{
|
|||
|
command.Parameters.AddWithValue("@EmployeeID", employeeId);
|
|||
|
}
|
|||
|
|
|||
|
command.ExecuteNonQuery();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
MessageBox.Show("Ошибка при сохранении данных: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
this.DialogResult = DialogResult.None;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Форма для отметки посещаемости
|
|||
|
public class AttendanceForm : Form
|
|||
|
{
|
|||
|
private string connectionString;
|
|||
|
private bool isArrival;
|
|||
|
private ComboBox cmbEmployees;
|
|||
|
|
|||
|
public AttendanceForm(string connString, bool arrival)
|
|||
|
{
|
|||
|
connectionString = connString;
|
|||
|
isArrival = arrival;
|
|||
|
|
|||
|
InitializeComponent();
|
|||
|
LoadEmployees();
|
|||
|
|
|||
|
this.Text = isArrival ? "Отметка прибытия" : "Отметка убытия";
|
|||
|
}
|
|||
|
|
|||
|
private void InitializeComponent()
|
|||
|
{
|
|||
|
this.Width = 400;
|
|||
|
this.Height = 200;
|
|||
|
this.StartPosition = FormStartPosition.CenterParent;
|
|||
|
this.FormBorderStyle = FormBorderStyle.FixedDialog;
|
|||
|
this.MaximizeBox = false;
|
|||
|
this.MinimizeBox = false;
|
|||
|
|
|||
|
// Заголовок
|
|||
|
Label lblHeader = new Label
|
|||
|
{
|
|||
|
Text = isArrival ? "Отметка прибытия сотрудника" : "Отметка убытия сотрудника",
|
|||
|
Font = new Font("Arial", 12, FontStyle.Bold),
|
|||
|
Location = new Point(50, 20),
|
|||
|
Width = 300,
|
|||
|
TextAlign = ContentAlignment.MiddleCenter
|
|||
|
};
|
|||
|
|
|||
|
// Выбор сотрудника
|
|||
|
Label lblEmployee = new Label
|
|||
|
{
|
|||
|
Text = "Сотрудник:",
|
|||
|
Location = new Point(30, 60),
|
|||
|
Width = 100
|
|||
|
};
|
|||
|
|
|||
|
cmbEmployees = new ComboBox
|
|||
|
{
|
|||
|
Location = new Point(130, 60),
|
|||
|
Width = 220,
|
|||
|
DropDownStyle = ComboBoxStyle.DropDownList
|
|||
|
};
|
|||
|
|
|||
|
// Кнопки
|
|||
|
Button btnSave = new Button
|
|||
|
{
|
|||
|
Text = "Отметить",
|
|||
|
DialogResult = DialogResult.OK,
|
|||
|
Location = new Point(130, 100),
|
|||
|
Width = 100
|
|||
|
};
|
|||
|
btnSave.Click += BtnSave_Click;
|
|||
|
|
|||
|
Button btnCancel = new Button
|
|||
|
{
|
|||
|
Text = "Отмена",
|
|||
|
DialogResult = DialogResult.Cancel,
|
|||
|
Location = new Point(250, 100),
|
|||
|
Width = 100
|
|||
|
};
|
|||
|
|
|||
|
// Добавляем компоненты на форму
|
|||
|
this.Controls.Add(lblHeader);
|
|||
|
this.Controls.Add(lblEmployee);
|
|||
|
this.Controls.Add(cmbEmployees);
|
|||
|
this.Controls.Add(btnSave);
|
|||
|
this.Controls.Add(btnCancel);
|
|||
|
|
|||
|
this.AcceptButton = btnSave;
|
|||
|
this.CancelButton = btnCancel;
|
|||
|
}
|
|||
|
|
|||
|
private void LoadEmployees()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
|
|||
|
{
|
|||
|
connection.Open();
|
|||
|
string query = "SELECT EmployeeID, LastName || ' ' || FirstName || ' ' || COALESCE(MiddleName, '') as FullName FROM Employees ORDER BY LastName, FirstName";
|
|||
|
SQLiteDataAdapter adapter = new SQLiteDataAdapter(query, connection);
|
|||
|
DataTable dt = new DataTable();
|
|||
|
adapter.Fill(dt);
|
|||
|
|
|||
|
cmbEmployees.DataSource = dt;
|
|||
|
cmbEmployees.DisplayMember = "FullName";
|
|||
|
cmbEmployees.ValueMember = "EmployeeID";
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
MessageBox.Show("Ошибка при загрузке списка сотрудников: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void BtnSave_Click(object sender, EventArgs e)
|
|||
|
{
|
|||
|
if (cmbEmployees.SelectedValue == null)
|
|||
|
{
|
|||
|
MessageBox.Show("Необходимо выбрать сотрудника", "Предупреждение", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|||
|
this.DialogResult = DialogResult.None;
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
using (SQLiteConnection connection = new SQLiteConnection(connectionString))
|
|||
|
{
|
|||
|
connection.Open();
|
|||
|
|
|||
|
if (isArrival)
|
|||
|
{
|
|||
|
// Отметка прибытия - создаем новую запись
|
|||
|
string query = "INSERT INTO Attendance (EmployeeID, ArrivalTime) VALUES (@EmployeeID, @ArrivalTime)";
|
|||
|
using (SQLiteCommand command = new SQLiteCommand(query, connection))
|
|||
|
{
|
|||
|
command.Parameters.AddWithValue("@EmployeeID", cmbEmployees.SelectedValue);
|
|||
|
command.Parameters.AddWithValue("@ArrivalTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
|||
|
command.ExecuteNonQuery();
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// Отметка убытия - ищем последнюю запись с прибытием для данного сотрудника
|
|||
|
string query = @"UPDATE Attendance SET DepartureTime = @DepartureTime
|
|||
|
WHERE EmployeeID = @EmployeeID AND DepartureTime IS NULL
|
|||
|
AND AttendanceID = (SELECT AttendanceID FROM Attendance
|
|||
|
WHERE EmployeeID = @EmployeeID AND DepartureTime IS NULL
|
|||
|
ORDER BY ArrivalTime DESC LIMIT 1)";
|
|||
|
using (SQLiteCommand command = new SQLiteCommand(query, connection))
|
|||
|
{
|
|||
|
command.Parameters.AddWithValue("@EmployeeID", cmbEmployees.SelectedValue);
|
|||
|
command.Parameters.AddWithValue("@DepartureTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
|
|||
|
int rowsAffected = command.ExecuteNonQuery();
|
|||
|
|
|||
|
if (rowsAffected == 0)
|
|||
|
{
|
|||
|
MessageBox.Show("Для данного сотрудника нет открытых записей о прибытии",
|
|||
|
"Информация", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|||
|
this.DialogResult = DialogResult.None;
|
|||
|
return;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
MessageBox.Show("Посещаемость успешно отмечена", "Успех", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|||
|
}
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
MessageBox.Show("Ошибка при сохранении данных: " + ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|||
|
this.DialogResult = DialogResult.None;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|