krona-staff/apps/KronaStaffTerminal/Models/TerminalModels.cs

163 lines
6.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Security.Cryptography;
using System.Text.Json.Serialization;
namespace KronaStaffTerminal.Models;
public sealed class EmployeeRecord
{
public string Id { get; set; } = UlidGenerator.New();
public string PersonnelNumber { get; set; } = "";
public string LastName { get; set; } = "";
public string FirstName { get; set; } = "";
public string Patronymic { get; set; } = "";
private string _displayName = "";
public string DisplayName
{
get
{
if (!string.IsNullOrWhiteSpace(_displayName)) return _displayName;
var parts = new[] { LastName, FirstName, Patronymic }.Where(p => !string.IsNullOrWhiteSpace(p));
var combined = string.Join(" ", parts);
return string.IsNullOrWhiteSpace(combined) ? "" : combined;
}
set => _displayName = value;
}
public string Position { get; set; } = "";
public string Gender { get; set; } = "";
public bool IsAdministrator { get; set; }
public bool IsBlocked { get; set; }
public DateTimeOffset? BlockedAtUtc { get; set; }
public List<FingerprintRecord> Fingerprints { get; set; } = [];
public string TelegramChatId { get; set; } = "";
public string VkPeerId { get; set; } = "";
public string MaxUserId { get; set; } = "";
public void SetFullName(string lastName, string firstName, string patronymic)
{
LastName = lastName?.Trim() ?? "";
FirstName = firstName?.Trim() ?? "";
Patronymic = patronymic?.Trim() ?? "";
var parts = new[] { LastName, FirstName, Patronymic }.Where(p => !string.IsNullOrWhiteSpace(p));
_displayName = string.Join(" ", parts);
}
// Legacy single-fingerprint fields are kept for one-way migration of existing encrypted state.
public int FingerprintId { get; set; }
public string? FingerprintTemplate { get; set; }
[JsonIgnore]
public bool HasFingerprint => Fingerprints.Count > 0;
[JsonIgnore]
public string FingerprintStatus => Fingerprints.Count switch
{
0 => "Отпечатков нет",
1 => "1 отпечаток",
2 or 3 or 4 => $"{Fingerprints.Count} отпечатка",
_ => $"{Fingerprints.Count} отпечатков"
};
[JsonIgnore]
public string AccessStatus => IsBlocked ? "Заблокирован" : IsAdministrator ? "Администратор" : "Сотрудник";
[JsonIgnore]
public string NotificationStatus
{
get
{
if (IsBlocked) return "Отключены";
var channels = new List<string>();
if (!string.IsNullOrWhiteSpace(TelegramChatId)) channels.Add("Telegram");
if (!string.IsNullOrWhiteSpace(VkPeerId)) channels.Add("VK");
if (!string.IsNullOrWhiteSpace(MaxUserId)) channels.Add("MAX");
return channels.Count == 0 ? "Не подключены" : string.Join(", ", channels);
}
}
[JsonIgnore]
public string GenderDisplay => string.IsNullOrWhiteSpace(Gender) ? "—" : Gender;
}
public sealed class FingerprintRecord
{
public int Id { get; set; }
public string Template { get; set; } = "";
public string Label { get; set; } = "";
public DateTimeOffset EnrolledAtUtc { get; set; } = DateTimeOffset.UtcNow;
}
public sealed class AttendanceRecord
{
public string Id { get; set; } = UlidGenerator.New();
public string EmployeeId { get; set; } = "";
public string EmployeeName { get; set; } = "";
public DateTimeOffset OccurredAtUtc { get; set; }
public int ReaderIndex { get; set; }
public string EventType { get; set; } = "Приход";
public bool IsAutomatic { get; set; }
public bool NotificationDelivered { get; set; }
public string? NotificationError { get; set; }
public bool ServerSynced { get; set; }
public string? ServerSyncError { get; set; }
[JsonIgnore]
public string LocalTime => OccurredAtUtc.ToLocalTime().ToString("dd.MM.yyyy HH:mm:ss");
[JsonIgnore]
public string DeliveryStatus => NotificationDelivered ? "Отправлено" : string.IsNullOrWhiteSpace(NotificationError) ? "Не настроено" : "Ошибка отправки";
}
public sealed class TerminalSettings
{
public string IpcAuthenticationKey { get; set; } = Convert.ToBase64String(RandomNumberGenerator.GetBytes(32));
public int ReaderIndex { get; set; }
public bool StartWithWindows { get; set; }
public string AdminPinSalt { get; set; } = "";
public string AdminPinHash { get; set; } = "";
public int AdminPinIterations { get; set; } = 120_000;
public int FailedAdminPinAttempts { get; set; }
public DateTimeOffset AdminPinBlockedUntilUtc { get; set; }
public int DuplicateScanGuardSeconds { get; set; } = 120;
public int MaximumShiftHours { get; set; } = 20;
public bool AutomaticCheckoutEnabled { get; set; }
public int AutomaticCheckoutHour { get; set; } = 2;
public int AutomaticCheckoutMinute { get; set; }
public DateTimeOffset LastAutomaticCheckoutUtc { get; set; }
public bool ShowEmployeeNamesOnTerminal { get; set; }
public bool TelegramEnabled { get; set; }
public string TelegramBotToken { get; set; } = "";
// Legacy global chat IDs are retained only so existing encrypted state remains readable.
public string TelegramChatId { get; set; } = "";
public bool VkEnabled { get; set; }
public string VkGroupToken { get; set; } = "";
public bool MaxEnabled { get; set; }
public string MaxBotToken { get; set; } = "";
public string MaxChatId { get; set; } = "";
public bool UpdateChecksEnabled { get; set; } = true;
public string UpdateFeedUrl { get; set; } = "https://git.ochenstarik.ru/api/v1/repos/ochenstarik/krona-staff/releases/latest";
public string UpdateAccessToken { get; set; } = "";
public string UpdateTrustedSignerThumbprint { get; set; } = "";
public string StaffServerUrl { get; set; } = "https://192.168.1.81:8453";
public string StaffServerToken { get; set; } = "";
public string StaffServerCertificateSha256 { get; set; } = "";
public string TerminalDeviceId { get; set; } = UlidGenerator.New();
public DateTimeOffset LastUpdateCheckUtc { get; set; }
}
public sealed class TerminalState
{
public List<EmployeeRecord> Employees { get; set; } = [];
public List<AttendanceRecord> Attendance { get; set; } = [];
public List<TerminalAuditRecord> SecurityAudit { get; set; } = [];
public TerminalSettings Settings { get; set; } = new();
}
public sealed class TerminalAuditRecord
{
public string Id { get; set; } = UlidGenerator.New();
public DateTimeOffset OccurredAtUtc { get; set; } = DateTimeOffset.UtcNow;
public string Action { get; set; } = "";
public string Actor { get; set; } = "";
public string Outcome { get; set; } = "";
public string Detail { get; set; } = "";
}