protected bool MoveWaybill(string archFileName, string fileName, DataRow drCurrent, BaseDocumentReader documentReader)
        {
            using (var cleaner = new FileCleaner()) {
                var supplierId = Convert.ToUInt32(drCurrent[WaybillSourcesTable.colFirmCode]);
                try {
                    var addresses  = With.Connection(c => documentReader.ParseAddressIds(c, supplierId, archFileName, fileName));
                    var formatFile = documentReader.FormatOutputFile(fileName, drCurrent);

                    cleaner.Watch(fileName);
                    cleaner.Watch(formatFile);

                    foreach (var addressId in addresses)
                    {
                        var log = DocumentReceiveLog.LogNoCommit(supplierId,
                                                                 (uint)addressId,
                                                                 formatFile,
                                                                 _currentDocumentType.DocType,
                                                                 "Получен с нашего FTP");

                        _logger.InfoFormat("WaybillLanSourceHandler: обработка файла {0}", fileName);
                        documentReader.ImportDocument(log, fileName);
                        new WaybillService().Process(new[] { log }.ToList());
                    }
                }
                catch (Exception e) {
                    var message = "Не удалось отформатировать документ.\nОшибка: " + e;
                    _logger.ErrorFormat("WaybillLanSourceHandler: {0}, archfilename {1}, fileName {2}, error {3}", message, archFileName, fileName, e);
                    DocumentReceiveLog.Log(supplierId, null, fileName, _currentDocumentType.DocType, message);
                    return(false);
                }
            }

            return(true);
        }
        protected DocumentReceiveLog GetLog(string file, DataRow source)
        {
            _logger.InfoFormat("WaybillEmailSourceHandler: обработка файла {0}", file);
            var supplierId = Convert.ToUInt32(source[WaybillSourcesTable.colFirmCode]);

            return(DocumentReceiveLog.LogNoCommit(
                       supplierId,
                       _addressId,
                       file,
                       _currentDocumentType.DocType,
                       "Получен по Email",
                       IMAPHandler.CurrentUID));
        }
        private List <DocumentReceiveLog> ProcessWaybill(DocType documentType, WaybillSource source, DownloadedFile downloadedFile)
        {
            var documentLogs = new List <DocumentReceiveLog>();
            var reader       = new SupplierFtpReader();

            var addressIds = With.Connection(c => reader.ParseAddressIds(c, source.Id, downloadedFile.FileName, downloadedFile.FileName));

            foreach (var addressId in addressIds)
            {
                // Если накладная - это архив, разархивируем логируем каждый файл и копируем в папку клиенту
                var waybillFiles = new[] { downloadedFile.FileName };
                try {
                    waybillFiles = FileHelper.TryExtractArchive(downloadedFile.FileName, downloadedFile.FileName + BaseSourceHandler.ExtrDirSuffix)
                                   ?? waybillFiles;
                }
                catch (ArchiveHelper.ArchiveException e) {
                    _logger.Warn($"Ошибка при извлечении файлов из архива {downloadedFile.FileName}", e);
                    WaybillService.SaveWaybill(downloadedFile.FileName);
                    continue;
                }

                foreach (var file in waybillFiles)
                {
                    var isNew = IsNewWaybill(source, (uint)addressId, Path.GetFileName(file), new FileInfo(file).Length);
                    if (!isNew)
                    {
                        _logger.DebugFormat("Файл {0} не является новой накладной, не обрабатываем его", file);
                        continue;
                    }
                    var log = DocumentReceiveLog.LogNoCommit(source.Id,
                                                             (uint)addressId,
                                                             file,
                                                             documentType,
                                                             "Получен с клиентского FTP");
                    _logger.InfoFormat("WaybillFtpSourceHandler: обработка файла {0}", file);
                    documentLogs.Add(log);
                }
            }
            return(documentLogs);
        }
        public void ProcessMessage(ISession session, MimeMessage message, UniqueId messageId = default(UniqueId))
        {
            //используется промежуточный почтовый ящик для транзита
            //в поле To будет именно он, этот же ящик используется для транзита прайс-листов
            var emails =
                message.To.OfType <MailboxAddress>().Where(s => !string.IsNullOrEmpty(s.Address)).Select(a => a.Address).ToArray();

            if (emails.Length == 0)
            {
                NotifyAdmin("У сообщения не указано ни одного получателя.", message);
                return;
            }
            var attachments = message.Attachments.Where(m => !String.IsNullOrEmpty(GetFileName(m)) && m.IsAttachment);

            if (!attachments.Any())
            {
                NotifyAdmin($"Отсутствуют вложения в письме от адреса {message.To.Implode()}", message);
                return;
            }

            var dtSources = session.Connection.Query <SupplierSelector>(@"
SELECT distinct
	s.Id as FirmCode,
	st.EMailTo
FROM farm.sourcetypes
	join farm.Sources as st on st.SourceTypeId = sourcetypes.Id
		join usersettings.PriceItems pi on pi.SourceId = st.ID
			join usersettings.PricesCosts pc on pc.PriceItemId = pi.ID
				join UserSettings.PricesData  as PD on PD.PriceCode = pc.PriceCode
					join Customers.Suppliers as s on s.Id = PD.FirmCode
WHERE
	sourcetypes.Type = 'EMail'
	and s.Disabled = 0
	and pd.AgencyEnabled = 1"    ).ToList();

            var sources = emails
                          .SelectMany(x => dtSources.Where(y => y.EmailTo?.IndexOf(x, StringComparison.OrdinalIgnoreCase) >= 0))
                          .Distinct()
                          .ToList();

            if (sources.Count > 1)
            {
                NotifyAdmin(
                    $"Для получателей {emails.Implode()} определено более одного поставщика." +
                    $" Определенные поставщики {sources.Select(x => x.FirmCode).Implode()}.", message);
                return;
            }
            if (sources.Count == 0)
            {
                NotifyAdmin(
                    $"Не удалось идентифицировать ни одного поставщика по адресам получателя {emails.Implode()}." +
                    $" Количество записей в источниках - {dtSources.Count}", message);
                return;
            }

            var source     = sources.First();
            var supplierId = source.FirmCode;
            var supplier   = session.Load <Supplier>(supplierId);

            using (var cleaner = new FileCleaner()) {
                foreach (var mimeEntity in attachments)
                {
                    //получение текущей директории
                    var filename = Path.Combine(DownHandlerPath, GetFileName(mimeEntity));
                    var files    = new List <string> {
                        filename
                    };

                    //сохранение содержимого в текущую директорию
                    using (var fs = new FileStream(filename, FileMode.Create))
                        ((MimePart)mimeEntity).ContentObject.DecodeTo(fs);

                    try {
                        files = FileHelper.TryExtractArchive(filename, cleaner.RandomDir())?.ToList()
                                ?? files;
                    } catch (ArchiveHelper.ArchiveException e) {
                        _logger.Warn($"Не удалось распаковать файл {filename}", e);
                        NotifyAdmin($"Не удалось распаковать файл {filename}.", message, supplier);
                        continue;
                    }

                    var logs = new List <DocumentReceiveLog>();
                    foreach (var file in files)
                    {
                        //нам нужно считать файл что бы узнать кто его отправил, по хорошему нам и не нужен пока что клиент
                        var doc = new WaybillFormatDetector().Parse(session, file, new DocumentReceiveLog(supplier, new Address(new Client()), DocType.Waybill));
                        if (doc == null)
                        {
                            NotifyAdmin($"Не удалось разобрать документ {file} нет подходящего формата.", message, supplier);
                            continue;
                        }
                        if (doc.Invoice?.RecipientId == null)
                        {
                            if (doc.Parser == nameof(WaybillSstParser))
                            {
                                NotifyAdmin($"В файле {file} не заполнено поле Код получателя.", message, supplier);
                            }
                            else
                            {
                                NotifyAdmin($"Формат файла {file} не соответствует согласованному формату sst. " +
                                            $"Поле 'Код получателя' не заполнено, возможно выбранный формат {doc.Parser} не считывает поле либо оно не заполнено в файла. " +
                                            $"Проверьте настройки формата {doc.Parser} и заполнение поля 'Код получателя' в файле.", message, supplier);
                            }
                            continue;
                        }

                        var result = session.Connection.Query <uint?>(@"
select ai.AddressId
from Customers.Intersection i
	join Customers.AddressIntersection ai on ai.IntersectionId = i.Id
	join Usersettings.Pricesdata pd on pd.PriceCode = i.PriceId
		join Customers.Suppliers s on s.Id = pd.FirmCode
where ai.SupplierDeliveryId = @supplierDeliveryId
	and s.Id  = @supplierId
group by ai.AddressId", new { @supplierDeliveryId = doc.Invoice.RecipientId, @supplierId = supplierId })
                                     .FirstOrDefault();

                        if (result == null)
                        {
                            NotifyAdmin($"Не удалось обработать документ {file} для кода получателя {doc.Invoice.RecipientId} не найден адрес доставки. " +
                                        $"Проверьте заполнение поля 'Код адреса доставки' в личном кабинете поставщика {supplierId}.",
                                        message, supplier);
                            continue;
                        }

                        _logger.InfoFormat($"Файл {file} обработан для кода получателя {doc.Invoice.RecipientId} выбран адрес {result.Value}");
                        logs.Add(DocumentReceiveLog.LogNoCommit(supplierId, result.Value, file, DocType.Waybill, "Получен по Email",
                                                                (int?)messageId.Id));
                    }
                    //если логи есть, значит файл распознан и найден соответствующий адрес доставки
                    if (logs.Count > 0)
                    {
                        var service = new WaybillService();
                        service.Process(logs);
                        if (service.Exceptions.Count > 0)
                        {
                            NotifyAdmin(service.Exceptions.First().Message, message, supplier);
                        }
                    }
                }
            }
        }