/
valzem
/
MatControl
Обзор
Документация
Войти
/
valzem
/
MatControl
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/MatControl.Business/ImportService.cs
328 строк
11 KB
MatControl Dev
Сортировка и поиск в списках, статусы в Движении, импорт с выбором файла, поле Отдел, скиллы
07 авг 2026, 16:45
07 авг 2026, 16:45
4bdbbb6
Код
Авторство
О чём код?
using MatControl.Data; using MatControl.Data.Import; using MatControl.Data.Repositories; using MatControl.Domain; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace MatControl.Business; public class ImportService { private readonly MatControlDbContext _context; private readonly ILogger<ImportService> _logger; private readonly IEmployeeRepository _employees; private readonly IAssetRepository _assets; private readonly ISupplyRepository _supplies; private readonly IAssetMovementRepository _movements; public ImportService( MatControlDbContext context, IEmployeeRepository employees, IAssetRepository assets, ISupplyRepository supplies, IAssetMovementRepository movements, ILogger<ImportService> logger) { _context = context; _employees = employees; _assets = assets; _supplies = supplies; _movements = movements; _logger = logger; } public async Task<OperationResult<ImportReport>> ImportAllAsync(string importDirectory) { var report = new ImportReport(); var phonebookPath = Path.Combine(importDirectory, "Телефонный_справочник_Облкомтруда.docx"); var osFiles = new[] { ("ОС_101.34.xls", "ОС_101.34"), ("ОС_21.34.xls", "ОС_21.34"), ("ОС_21.36.xls", "ОС_21.36") }; var suppliesPath = Path.Combine(importDirectory, "МЗ_105.36.xls"); try { await ImportEmployeesAsync(phonebookPath, report); foreach (var (file, key) in osFiles) { await ImportAssetsAsync(Path.Combine(importDirectory, file), key, report); } await ImportSuppliesAsync(suppliesPath, report); await _context.SaveChangesAsync(); return OperationResult<ImportReport>.Ok(report); } catch (Exception ex) { _logger.LogError(ex, "Ошибка при импорте данных"); return OperationResult<ImportReport>.Fail($"Не удалось выполнить импорт: {ex.Message}"); } } public async Task<OperationResult<ImportReport>> ImportEmployeesFromFileAsync(string path) { var report = new ImportReport(); try { if (!File.Exists(path)) { return OperationResult<ImportReport>.Fail("Файл не найден"); } await ImportEmployeesCoreAsync(path, report); await _context.SaveChangesAsync(); return OperationResult<ImportReport>.Ok(report); } catch (Exception ex) { _logger.LogError(ex, "Ошибка при импорте сотрудников из {Path}", path); return OperationResult<ImportReport>.Fail($"Не удалось выполнить импорт: {ex.Message}"); } } private async Task ImportEmployeesAsync(string path, ImportReport report) { if (!File.Exists(path)) { report.Warnings.Add($"Файл телефонного справочника не найден: {path}"); return; } await ImportEmployeesCoreAsync(path, report); } private async Task ImportEmployeesCoreAsync(string path, ImportReport report) { var parsed = PhonebookParser.Parse(path); var existingByName = (await _employees.GetAllAsync()) .ToDictionary( e => e.FullName.Trim().ToLowerInvariant(), e => e, StringComparer.OrdinalIgnoreCase); foreach (var item in parsed) { var key = item.FullName.Trim().ToLowerInvariant(); if (existingByName.TryGetValue(key, out var existingEmployee)) { if (string.IsNullOrWhiteSpace(existingEmployee.Department) && !string.IsNullOrWhiteSpace(item.Department)) { existingEmployee.Department = item.Department; await _employees.UpdateAsync(existingEmployee); report.EmployeesUpdated++; } else { report.EmployeesSkipped++; } continue; } var employee = new Employee { FullName = item.FullName, Position = item.Position, Department = item.Department, Room = item.Room, Phone = item.Phone }; await _employees.AddAsync(employee); existingByName[key] = employee; report.EmployeesProcessed++; } } public async Task<OperationResult<ImportReport>> ImportAssetsWithMappingAsync( IReadOnlyList<ParsedAsset> parsed, string sourceKey) { var report = new ImportReport(); try { await ImportAssetsCoreAsync(parsed, sourceKey, report); await _context.SaveChangesAsync(); return OperationResult<ImportReport>.Ok(report); } catch (Exception ex) { _logger.LogError(ex, "Ошибка при импорте ОС с сопоставлением колонок"); return OperationResult<ImportReport>.Fail($"Не удалось выполнить импорт ОС: {ex.Message}"); } } public async Task<OperationResult<ImportReport>> ImportSuppliesWithMappingAsync( IReadOnlyList<ParsedSupply> parsed) { var report = new ImportReport(); try { await ImportSuppliesCoreAsync(parsed, report); await _context.SaveChangesAsync(); return OperationResult<ImportReport>.Ok(report); } catch (Exception ex) { _logger.LogError(ex, "Ошибка при импорте МЗ с сопоставлением колонок"); return OperationResult<ImportReport>.Fail($"Не удалось выполнить импорт МЗ: {ex.Message}"); } } public async Task<OperationResult<ImportReport>> ImportAssetsFromFileAsync(string path, string sourceKey) { var report = new ImportReport(); try { if (!File.Exists(path)) { return OperationResult<ImportReport>.Fail("Файл не найден"); } var parsed = ExcelImporter.ReadAssets(path, sourceKey); if (parsed.Count == 0) { report.Warnings.Add("Не удалось распознать структуру файла автоматически"); } await ImportAssetsCoreAsync(parsed, sourceKey, report); await _context.SaveChangesAsync(); return OperationResult<ImportReport>.Ok(report); } catch (Exception ex) { _logger.LogError(ex, "Ошибка при импорте ОС из {Path}", path); return OperationResult<ImportReport>.Fail($"Не удалось выполнить импорт ОС: {ex.Message}"); } } public async Task<OperationResult<ImportReport>> ImportSuppliesFromFileAsync(string path) { var report = new ImportReport(); try { if (!File.Exists(path)) { return OperationResult<ImportReport>.Fail("Файл не найден"); } var parsed = ExcelImporter.ReadSupplies(path); if (parsed.Count == 0) { report.Warnings.Add("Не удалось распознать структуру файла автоматически"); } await ImportSuppliesCoreAsync(parsed, report); await _context.SaveChangesAsync(); return OperationResult<ImportReport>.Ok(report); } catch (Exception ex) { _logger.LogError(ex, "Ошибка при импорте МЗ из {Path}", path); return OperationResult<ImportReport>.Fail($"Не удалось выполнить импорт МЗ: {ex.Message}"); } } private async Task ImportAssetsAsync(string path, string sourceKey, ImportReport report) { if (!File.Exists(path)) { report.Warnings.Add($"Файл ОС не найден: {path}"); return; } var parsed = ExcelImporter.ReadAssets(path, sourceKey); await ImportAssetsCoreAsync(parsed, sourceKey, report); } private async Task ImportAssetsCoreAsync(IReadOnlyList<ParsedAsset> parsed, string sourceKey, ImportReport report) { var mol = await _employees.GetResponsibleAsync(); if (mol is null) { report.Warnings.Add("Не найден МОЛ, ОС не импортированы"); return; } var existingNumbers = (await _assets.GetAllAsync()) .Select(a => a.InventoryNumber.Trim().ToLowerInvariant()) .ToHashSet(); foreach (var item in parsed) { if (existingNumbers.Contains(item.InventoryNumber.Trim().ToLowerInvariant())) { report.AssetsSkipped++; continue; } var asset = new Asset { InventoryNumber = item.InventoryNumber, Name = item.Name, YearInUse = item.YearInUse, State = item.State, Price = item.Price, Category = sourceKey }; await _assets.AddAsync(asset); await _movements.AddAsync(new AssetMovement { Asset = asset, FromEmployeeId = mol.Id, ToEmployeeId = mol.Id, TransferDate = DateTime.Today, QuantityTransferred = 1, MovementType = MovementType.Выдача, IsActive = true }); existingNumbers.Add(item.InventoryNumber.Trim().ToLowerInvariant()); report.AssetsProcessed++; } } private async Task ImportSuppliesAsync(string path, ImportReport report) { if (!File.Exists(path)) { report.Warnings.Add($"Файл МЗ не найден: {path}"); return; } var parsed = ExcelImporter.ReadSupplies(path); await ImportSuppliesCoreAsync(parsed, report); } private async Task ImportSuppliesCoreAsync(IReadOnlyList<ParsedSupply> parsed, ImportReport report) { var existingNames = (await _supplies.GetAllAsync()) .Select(s => s.Name.Trim().ToLowerInvariant()) .ToHashSet(); foreach (var item in parsed) { if (existingNames.Contains(item.Name.Trim().ToLowerInvariant())) { report.SuppliesSkipped++; continue; } await _supplies.AddAsync(new Supply { Name = item.Name, Quantity = item.Quantity, Price = item.Price, TotalSum = item.TotalSum }); existingNames.Add(item.Name.Trim().ToLowerInvariant()); report.SuppliesProcessed++; } } }