Compare commits

...

1 Commits

Author SHA1 Message Date
Mikan
637b7ff815 update 2025-05-23 19:20:57 +03:00
19 changed files with 1039 additions and 12 deletions

View File

@@ -2,9 +2,19 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:OfficeFlow"
xmlns:converters="clr-namespace:OfficeFlow.Utils.Converters"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<!-- Регистрация конвертера -->
<converters:CountConverter x:Key="CountConverter"/>
<converters:DateConverter x:Key="DateConverter"/>
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter"/>
<!-- Определение стиля для кнопки -->
<Style x:Key="AccentButtonStyle" TargetType="Button">
<Setter Property="Background" Value="#4CAF50" />

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OfficeFlow.Models
{
public partial class Employee
{
public User User
{
get
{
return this.User_Employee.FirstOrDefault()?.User;
}
set
{
var userEmployee = this.User_Employee.FirstOrDefault();
if (userEmployee == null)
{
userEmployee = new User_Employee
{
Employee = this,
};
App.Entities.User_Employee.Add(userEmployee);
}
userEmployee.User = value;
}
}
}
}

View File

@@ -33,5 +33,33 @@ namespace OfficeFlow.Models
}
}
public Employee Employee
{
get
{
return this.User_Employee.FirstOrDefault()?.Employee;
}
set
{
var userEmployee = this.User_Employee.FirstOrDefault();
if (userEmployee == null)
{
userEmployee = new User_Employee
{
User = this,
};
App.Entities.User_Employee.Add(userEmployee);
}
userEmployee.Employee = value;
}
}
}
}

View File

@@ -64,13 +64,23 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Models\Utils\Employee.cs" />
<Compile Include="Models\Utils\User.cs" />
<Compile Include="Pages\EmployeePages\CreateEmployeePage.xaml.cs">
<DependentUpon>CreateEmployeePage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\EmployeePages\CreateUserPage.xaml.cs">
<DependentUpon>CreateUserPage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\EmployeePages\EmployeesPage.xaml.cs">
<DependentUpon>EmployeesPage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\EmployeePages\EmployeesPositionsPage.xaml.cs">
<DependentUpon>EmployeesPositionsPage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\EmployeePages\LinkUserPage.xaml.cs">
<DependentUpon>LinkUserPage.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\EmployeePages\NewEmployeePage.xaml.cs">
<DependentUpon>NewEmployeePage.xaml</DependentUpon>
</Compile>
@@ -83,6 +93,9 @@
<Compile Include="Pages\MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Utils\Converters\CountConverter.cs" />
<Compile Include="Utils\Converters\DateConverter.cs" />
<Compile Include="Utils\Converters\NullToVisibilityConverter.cs" />
<Compile Include="Utils\Session.cs" />
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
@@ -96,6 +109,14 @@
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="Pages\EmployeePages\CreateEmployeePage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\EmployeePages\CreateUserPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\EmployeePages\EmployeesPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -104,6 +125,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\EmployeePages\LinkUserPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\EmployeePages\NewEmployeePage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@@ -0,0 +1,51 @@
<Page x:Class="OfficeFlow.Pages.EmployeePages.CreateEmployeePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:OfficeFlow.Pages.EmployeePages"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="Создать сотрудника">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Заголовок -->
<TextBlock Text="Создать нового сотрудника" FontSize="20" FontWeight="Bold" Margin="0,0,0,20"/>
<!-- ФИО -->
<StackPanel Grid.Row="1" Orientation="Vertical" Margin="0,0,0,10">
<TextBlock Text="ФИО:" FontSize="16"/>
<TextBox x:Name="TBFullName" Width="300" Height="30"/>
</StackPanel>
<!-- Должность -->
<StackPanel Grid.Row="2" Orientation="Vertical" Margin="0,0,0,10">
<TextBlock Text="Должность:" FontSize="16"/>
<ComboBox x:Name="CBPositions" DisplayMemberPath="PositionName" Width="300" Height="30"/>
</StackPanel>
<!-- Контактная информация -->
<StackPanel Grid.Row="3" Orientation="Vertical" Margin="0,0,0,10">
<TextBlock Text="Контактная информация:" FontSize="16"/>
<TextBox x:Name="TBContactInfo" Width="300" Height="30"/>
</StackPanel>
<!-- Кнопки -->
<StackPanel Grid.Row="5" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="Отмена" Width="100" Height="30" Margin="0,0,10,0" Click="Cancel_Click" IsCancel="True"/>
<Button Content="Создать" Width="100" Height="30" Click="CreateEmployee_Click" Style="{StaticResource AccentButtonStyle}"/>
</StackPanel>
</Grid>
</Page>

View File

@@ -0,0 +1,86 @@
using OfficeFlow.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OfficeFlow.Pages.EmployeePages
{
/// <summary>
/// Interaction logic for CreateEmployee.xaml
/// </summary>
public partial class CreateEmployeePage : Page
{
public CreateEmployeePage()
{
InitializeComponent();
LoadData();
}
private void LoadData()
{
// Загружаем должности
var positions = App.Entities.Positions.ToList();
CBPositions.ItemsSource = positions;
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
NavigationService.GoBack();
}
private void CreateEmployee_Click(object sender, RoutedEventArgs e)
{
string fullName = TBFullName.Text.Trim();
Position position = CBPositions.SelectedValue as Position;
string contactInfo = TBContactInfo.Text.Trim();
if (string.IsNullOrEmpty(fullName) || position == null)
{
MessageBox.Show("Заполните все обязательные поля.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
using (var transaction = App.Entities.Database.BeginTransaction())
{
try
{
// Создаем нового сотрудника
var newEmployee = new Employee
{
FullName = fullName,
ContactInfo = string.IsNullOrEmpty(contactInfo) ? null : contactInfo,
Position = position,
EmployeeStatus = App.Entities.EmployeeStatuses.Where(es => es.StatusName == "Работает").FirstOrDefault(),
};
App.Entities.Employees.Add(newEmployee);
App.Entities.SaveChanges();
transaction.Commit();
MessageBox.Show("Сотрудник успешно создан.", "Успех", MessageBoxButton.OK, MessageBoxImage.Information);
NavigationService.GoBack();
}
catch (Exception ex)
{
transaction.Rollback();
MessageBox.Show($"Ошибка при создании сотрудника: {ex.Message}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
}
}

View File

@@ -0,0 +1,55 @@
<Page x:Class="OfficeFlow.Pages.EmployeePages.CreateUserPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:OfficeFlow.Pages.EmployeePages"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="Создать пользователя">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Заголовок -->
<TextBlock Text="Создать нового пользователя" FontSize="20" FontWeight="Bold" Margin="0,0,0,20"/>
<!-- Логин -->
<StackPanel Grid.Row="1" Orientation="Vertical" Margin="0,0,0,10">
<TextBlock Text="Логин:" FontSize="16"/>
<TextBox x:Name="TBLLogin" Width="300" Height="30"/>
</StackPanel>
<!-- Пароль -->
<StackPanel Grid.Row="2" Orientation="Vertical" Margin="0,0,0,10">
<TextBlock Text="Пароль:" FontSize="16"/>
<PasswordBox x:Name="PBPassword" Width="300" Height="30"/>
</StackPanel>
<!-- Email -->
<StackPanel Grid.Row="3" Orientation="Vertical" Margin="0,0,0,10">
<TextBlock Text="Email:" FontSize="16"/>
<TextBox x:Name="TBLEmail" Width="300" Height="30"/>
</StackPanel>
<!-- Роль -->
<StackPanel Grid.Row="4" Orientation="Vertical" Margin="0,0,0,10">
<TextBlock Text="Роль:" FontSize="16"/>
<ComboBox x:Name="CBRoles" DisplayMemberPath="RoleName" SelectedValuePath="RoleID" Width="300" Height="30"/>
</StackPanel>
<!-- Кнопки -->
<StackPanel Grid.Row="5" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="Отмена" Width="100" Height="30" Margin="0,0,10,0" Click="Cancel_Click" IsCancel="True"/>
<Button Content="Создать" Width="100" Height="30" Click="CreateUser_Click" Style="{StaticResource AccentButtonStyle}"/>
</StackPanel>
</Grid>
</Page>

View File

@@ -0,0 +1,94 @@
using OfficeFlow.Models;
using OfficeFlow.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OfficeFlow.Pages.EmployeePages
{
/// <summary>
/// Interaction logic for CreateUserPage.xaml
/// </summary>
public partial class CreateUserPage : Page
{
private Employee _employee;
public CreateUserPage(Employee employee)
{
InitializeComponent();
_employee = employee ?? throw new ArgumentNullException(nameof(employee));
LoadRoles();
}
private void LoadRoles()
{
// Загружаем все доступные роли
var roles = App.Entities.Roles.ToList();
CBRoles.ItemsSource = roles;
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
NavigationService.GoBack();
}
private void CreateUser_Click(object sender, RoutedEventArgs e)
{
string login = TBLLogin.Text.Trim();
string password = PBPassword.Password.Trim();
string email = TBLEmail.Text.Trim();
var selectedRole = CBRoles.SelectedItem as Role;
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || selectedRole == null)
{
MessageBox.Show("Заполните все поля и выберите роль.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
email = String.IsNullOrWhiteSpace(email) ? null : email;
using (var transaction = App.Entities.Database.BeginTransaction())
{
try
{
// Создаем нового пользователя
var newUser = Session.CreateUser(
login,
password,
selectedRole,
email
);
newUser.Employee = _employee;
App.Entities.SaveChanges();
transaction.Commit();
MessageBox.Show("Пользователь успешно создан.", "Успех", MessageBoxButton.OK, MessageBoxImage.Information);
NavigationService.GoBack();
}
catch (Exception ex)
{
transaction.Rollback();
MessageBox.Show($"Ошибка при создании пользователя: {ex.Message}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
}
}

View File

@@ -6,9 +6,64 @@
xmlns:local="clr-namespace:OfficeFlow.Pages.EmployeePages"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="EmployeesPage">
Title="Сотрудники" Loaded="Page_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<DataGrid x:Name="DGData" AutoGenerateColumns="False" CellEditEnding="DGData_CellEditEnding" PreviewKeyDown="DGData_PreviewKeyDown">
<DataGrid.Columns>
<DataGridTextColumn Header="ФИО" Binding="{Binding FullName, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridComboBoxColumn
Header="Должность"
SelectedValueBinding="{Binding PositionID, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="PositionName"
SelectedValuePath="PositionID"
x:Name="DGCBPosition"
/>
<DataGridTextColumn Header="Контактная информация" Binding="{Binding ContactInfo, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn
Header="Дата приёма на работу"
Binding="{Binding HireDate, Converter={StaticResource DateConverter}, UpdateSourceTrigger=PropertyChanged}"
/>
<DataGridComboBoxColumn
Header="Статус"
SelectedValueBinding="{Binding EmployeeStatus, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="StatusName"
x:Name="DGCBStatus"
/>
<DataGridTextColumn
Header="Логин пользователя"
Binding="{Binding User.Login}"
IsReadOnly="True"/>
<!-- Столбец с кнопкой "Создать учётную запись" -->
<DataGridTemplateColumn Header="Действия">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!-- Кнопка "Создать учётную запись" -->
<Button
Content="Создать учётную запись"
Visibility="{Binding User, Converter={StaticResource NullToVisibilityConverter}}"
Click="CreateAccount_Click" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<StackPanel Grid.Row="1">
<Button x:Name="BNew" Content="Добавить" Style="{StaticResource AccentButtonStyle}" Click="BNew_Click"/>
<Button x:Name="BBack" Content="Назад" Click="BBack_Click"/>
</StackPanel>
</Grid>
</Page>

View File

@@ -1,5 +1,7 @@
using System;
using OfficeFlow.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -23,6 +25,152 @@ namespace OfficeFlow.Pages.EmployeePages
public EmployeesPage()
{
InitializeComponent();
DGCBPosition.ItemsSource = App.Entities.Positions.ToList();
DGCBStatus.ItemsSource = App.Entities.EmployeeStatuses.ToList();
}
private void Refresh()
{
DGData.ItemsSource = new ObservableCollection<Employee>(App.Entities.Employees.ToList());
}
private void BBack_Click(object sender, RoutedEventArgs e)
{
NavigationService.GoBack();
}
private void DGData_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.EditAction != DataGridEditAction.Commit)
{
return;
}
if (e.Row.Item is Employee newPosition)
{
using (var transaction = App.Entities.Database.BeginTransaction())
{
try
{
Employee employee = App.Entities.Employees.Find(newPosition.EmployeeID);
if (employee == null)
{
employee = new Employee();
App.Entities.Employees.Add(employee);
}
employee.FullName = newPosition.FullName;
employee.Position = newPosition.Position;
employee.ContactInfo = newPosition.ContactInfo;
employee.HireDate = newPosition.HireDate;
employee.EmployeeStatus = newPosition.EmployeeStatus;
//employee.User
App.Entities.SaveChanges();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
MessageBox.Show(
"Ошибка при добавлении, проверьте данные!",
"Не удалось добавить данные в БД",
MessageBoxButton.OK,
MessageBoxImage.Error
);
}
}
Refresh();
}
}
private void DGData_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key != Key.Delete)
{
return;
}
var selectedPosition = DGData.SelectedItem as Employee;
// Получаем выбранную строку
if (selectedPosition == null || selectedPosition.EmployeeID == 0)
{
return;
}
var result = MessageBox.Show(
$"Вы уверены, что хотите удалить '{selectedPosition.FullName}'? Лучше заменить у него статус!",
"Подтверждение удаления",
MessageBoxButton.YesNo,
MessageBoxImage.Warning);
if (result == MessageBoxResult.No)
{
return;
}
using (var transaction = App.Entities.Database.BeginTransaction())
{
try
{
App.Entities.Employees.Remove(selectedPosition);
App.Entities.SaveChanges();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
MessageBox.Show(
"Ошибка при удалении, проверьте данные!",
"Не удалось удалить данные из БД",
MessageBoxButton.OK,
MessageBoxImage.Error
);
}
}
Refresh();
}
private void CreateAccount_Click(object sender, RoutedEventArgs e)
{
if (sender is Button button && button.DataContext is Employee employee)
{
// Передаем данные сотрудника на страницу LinkUser
NavigationService.Navigate(new LinkUserPage(employee));
}
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
Refresh();
}
private void BNew_Click(object sender, RoutedEventArgs e)
{
NavigationService.Navigate(new CreateEmployeePage());
}
}
}

View File

@@ -6,9 +6,25 @@
xmlns:local="clr-namespace:OfficeFlow.Pages.EmployeePages"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="EmployeesPositionsPage">
Title="Настройка должностей">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<DataGrid x:Name="DGData" AutoGenerateColumns="False" CellEditEnding="DGData_CellEditEnding" PreviewKeyDown="DGData_PreviewKeyDown">
<DataGrid.Columns>
<DataGridTextColumn Header="Название должности*" Binding="{Binding PositionName, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Описание" Binding="{Binding PositionDescription, UpdateSourceTrigger=PropertyChanged}" Width="auto"/>
<DataGridTextColumn
Header="Количество сотрудников"
Binding="{Binding Employees, Converter={StaticResource CountConverter}}"
IsReadOnly="True"
/>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="BBack" Grid.Row="1" Content="Назад" Click="BBack_Click"/>
</Grid>
</Page>

View File

@@ -1,5 +1,8 @@
using System;
using OfficeFlow.Models;
using OfficeFlow.Utils;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@@ -23,6 +26,142 @@ namespace OfficeFlow.Pages.EmployeePages
public EmployeesPositionsPage()
{
InitializeComponent();
Refresh();
}
private void Refresh()
{
DGData.ItemsSource = new ObservableCollection<Position>(App.Entities.Positions.ToList());
}
private void BBack_Click(object sender, RoutedEventArgs e)
{
NavigationService.GoBack();
}
private void DGData_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.EditAction != DataGridEditAction.Commit)
{
return;
}
if (e.Row.Item is Position newPosition)
{
if (String.IsNullOrWhiteSpace(newPosition.PositionName))
{
MessageBox.Show(
"Необходимо сначала указать название",
"Неправильный порядок добавления данных",
MessageBoxButton.OK,
MessageBoxImage.Exclamation
);
return;
}
using (var transaction = App.Entities.Database.BeginTransaction())
{
try
{
Position position = App.Entities.Positions.Find(newPosition.PositionID);
if (position == null)
{
position = new Position();
App.Entities.Positions.Add(position);
}
position.PositionName = newPosition.PositionName;
position.PositionDescription = String.IsNullOrWhiteSpace(newPosition.PositionDescription)?null: newPosition.PositionDescription.Trim();
App.Entities.SaveChanges();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
MessageBox.Show(
"Ошибка при добавлении, проверьте данные!",
"Не удалось добавить данные в БД",
MessageBoxButton.OK,
MessageBoxImage.Error
);
}
}
Refresh();
}
}
private void DGData_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key != Key.Delete)
{
return;
}
var selectedPosition = DGData.SelectedItem as Position;
// Получаем выбранную строку
if (selectedPosition == null || selectedPosition.PositionID == 0)
{
return;
}
if (selectedPosition.Employees.Count() > 0)
{
MessageBox.Show(
"Некорретная операция!",
"Нельзя удалить пока есть работники с такой должностью",
MessageBoxButton.OK,
MessageBoxImage.Error
);
return;
}
var result = MessageBox.Show(
$"Вы уверены, что хотите удалить должность '{selectedPosition.PositionName}'?",
"Подтверждение удаления",
MessageBoxButton.YesNo,
MessageBoxImage.Warning);
if (result == MessageBoxResult.No) {
return;
}
using (var transaction = App.Entities.Database.BeginTransaction())
{
try
{
App.Entities.Positions.Remove(selectedPosition);
App.Entities.SaveChanges();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
MessageBox.Show(
"Ошибка при удалении, проверьте данные!",
"Не удалось удалить данные из БД",
MessageBoxButton.OK,
MessageBoxImage.Error
);
}
}
Refresh();
}
}
}

View File

@@ -0,0 +1,36 @@
<Page x:Class="OfficeFlow.Pages.EmployeePages.LinkUserPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:OfficeFlow.Pages.EmployeePages"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="Связать пользователя" Loaded="Page_Loaded">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Заголовок -->
<TextBlock Text="Связать сотрудника с пользователем" FontSize="20" FontWeight="Bold" Margin="0,0,0,20"/>
<!-- Выбор пользователя -->
<StackPanel Grid.Row="1" Orientation="Vertical">
<TextBlock Text="Выберите пользователя:" FontSize="16" Margin="0,0,0,10"/>
<ComboBox x:Name="CBUsers" DisplayMemberPath="Login" SelectedValuePath="UserID" Margin="0,0,0,20" Width="300"/>
<!-- Кнопка "Создать нового пользователя" -->
<Button Content="Создать нового пользователя" Width="200" Height="30" Click="CreateNewUser_Click" HorizontalAlignment="Left"/>
</StackPanel>
<!-- Кнопка "Связать" -->
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="Отмена" Width="100" Height="30" Margin="0,0,10,0" Click="Cancel_Click" IsCancel="True"/>
<Button Content="Связать" Width="100" Height="30" Click="LinkUser_Click"/>
</StackPanel>
</Grid>
</Page>

View File

@@ -0,0 +1,98 @@
using OfficeFlow.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OfficeFlow.Pages.EmployeePages
{
/// <summary>
/// Interaction logic for LinkUserPage.xaml
/// </summary>
public partial class LinkUserPage : Page
{
private Employee _employee;
public LinkUserPage(Employee employee)
{
InitializeComponent();
_employee = employee ?? throw new ArgumentNullException(nameof(employee));
LoadAvailableUsers();
}
private void LoadAvailableUsers()
{
// Загружаем пользователей, у которых нет связанного сотрудника
var availableUsers = App.Entities.Users
.Where(u => u.User_Employee.Count() == 0)
.ToList();
CBUsers.ItemsSource = availableUsers;
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
NavigationService.GoBack();
}
private void CreateNewUser_Click(object sender, RoutedEventArgs e)
{
// Переход на страницу создания нового пользователя
NavigationService.Navigate(new CreateUserPage(_employee));
}
private void LinkUser_Click(object sender, RoutedEventArgs e)
{
if (CBUsers.SelectedItem is User selectedUser)
{
using (var transaction = App.Entities.Database.BeginTransaction())
{
try
{
// Находим сотрудника и связываем его с выбранным пользователем
var employee = App.Entities.Employees.Find(_employee.EmployeeID);
if (employee != null)
{
employee.User = selectedUser;
App.Entities.SaveChanges();
transaction.Commit();
}
MessageBox.Show("Пользователь успешно связан.", "Успех", MessageBoxButton.OK, MessageBoxImage.Information);
NavigationService.GoBack();
}
catch (Exception ex)
{
transaction.Rollback();
MessageBox.Show($"Ошибка при связывании пользователя: {ex.Message}", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
else
{
MessageBox.Show("Выберите пользователя из списка.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
if (_employee.User != null)
{
NavigationService.GoBack();
}
}
}
}

View File

@@ -35,10 +35,22 @@ namespace OfficeFlow.Pages
string roleName = Session.CurrentUser.Role.RoleName;
if (roleName == "Администратор")
{
MainMenu.Items.Add(CreateAdminMenu());
switch (roleName)
{
case "Администратор":
MainMenu.Items.Add(CreateAdminMenu());
MainMenu.Items.Add(CreateManagerMenu());
MainMenu.Items.Add(CreateAccountantMenu());
break;
case "Менеджер":
MainMenu.Items.Add(CreateManagerMenu());
break;
case "Бухгалтер":
MainMenu.Items.Add(CreateAccountantMenu());
break;
default:
break;
}
@@ -123,6 +135,37 @@ namespace OfficeFlow.Pages
return adminMenuItem;
}
private MenuItem CreateManagerMenu()
{
MenuItem managerMenuItem = new MenuItem { Header = "Управление" };
var tenantsMenuItem = new MenuItem { Header = "Арендаторы" };
tenantsMenuItem.Click += (sender, e) => throw new NotImplementedException();
managerMenuItem.Items.Add(tenantsMenuItem);
var roomsMenuItem = new MenuItem { Header = "Помещения" };
roomsMenuItem.Click += (sender, e) => throw new NotImplementedException();
managerMenuItem.Items.Add(roomsMenuItem);
return managerMenuItem;
}
private MenuItem CreateAccountantMenu()
{
MenuItem accountantMenuItem = new MenuItem { Header = "Финансы" };
var rentalPaymentsMenuItem = new MenuItem { Header = "Платежи за аренду" };
rentalPaymentsMenuItem.Click += (sender, e) => throw new NotImplementedException();
accountantMenuItem.Items.Add(rentalPaymentsMenuItem);
var servicePaymentsMenuItem = new MenuItem { Header = "Платежи за услуги" };
servicePaymentsMenuItem.Click += (sender, e) => throw new NotImplementedException();
accountantMenuItem.Items.Add(servicePaymentsMenuItem);
return accountantMenuItem;
}
public void ClearHistory()
{
while (NavigationService.CanGoBack)

View File

@@ -0,0 +1,37 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace OfficeFlow.Utils.Converters
{
public class CountConverter : IValueConverter
{
/// <summary>
/// Преобразует входное значение (коллекцию) в количество элементов.
/// </summary>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// Проверяем, является ли входное значение коллекцией
if (value is ICollection collection)
{
return collection.Count;
}
// Если значение не является коллекцией, возвращаем 0
return 0;
}
/// <summary>
/// Обратное преобразование (не используется в данном случае).
/// </summary>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace OfficeFlow.Utils.Converters
{
public class DateConverter : IValueConverter
{
/// <summary>
/// Преобразует входное значение даты в строку в заданном формате.
/// </summary>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is DateTime date)
{
// Если передан параметр, используем его как формат даты
string format = parameter as string ?? "dd.MM.yyyy";
return date.ToString(format);
}
// Если значение не является датой, возвращаем пустую строку
return string.Empty;
}
/// <summary>
/// Обратное преобразование (строка -> дата).
/// </summary>
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string strDate && DateTime.TryParse(strDate, out DateTime result))
{
return result;
}
// Если преобразование невозможно, возвращаем null
return null;
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows;
namespace OfficeFlow.Utils.Converters
{
public class NullToVisibilityConverter : IValueConverter
{
/// <summary>
/// Преобразует null в Visibility.Collapsed и наоборот.
/// </summary>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value == null ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -61,10 +61,7 @@ namespace OfficeFlow.Utils
{
throw new Exception("Пользователь с таким логином уже существует.");
}
if (App.Entities.Users.Any(u => u.Email == email))
{
throw new Exception("Пользователь с таким email уже существует.");
}
// Создаем нового пользователя
var newUser = new User