В практике автоматизации розничной торговли часто возникает задача интеграции 1С с внешними кассовыми системами, такими как Shoppy. Основной сценарий взаимодействия заключается в получении ежедневных отчетов о продажах в виде текстовых файлов. Разберем подробно, как создать внешнюю обработку, которая по нажатию одной кнопки будет считывать файл, фильтровать данные по ключевым полям (код магазина, дата, тип операции) и загружать их в информационную базу 1С.
Первым делом нам необходимо подготовить инструмент взаимодействия с пользователем. Создадим внешнюю обработку в конфигураторе. На форме обработки разместим кнопку, которую назовем ВыполнитьВыгрузку (технически это будет загрузка данных в 1С, но для пользователя мы сохраняем привычную терминологию). Для этой кнопки создадим команду. Рассмотрим, как это выглядит в модуле формы:
&НаКлиенте
Процедура ВыполнитьВыгрузку(Команда)
// Сначала выберем файл на диске
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
Диалог.Фильтр = "Текстовые файлы (*.txt)|*.txt";
Если Диалог.Выбрать() Тогда
ПутьКФайлу = Диалог.ПолноеИмяФайла;
// Передаем выполнение на сервер для обработки данных
ЗагрузитьДанныеНаСервере(ПутьКФайлу);
КонецЕсли;
КонецПроцедуры
Проанализируем доступные инструменты платформы 1С для работы с текстом. В обсуждениях часто упоминается объект ТекстовыйДокумент. Он прост в использовании, но имеет существенный недостаток: при чтении файл целиком загружается в оперативную память. Если файл продаж за месяц окажется слишком объемным, это может привести к замедлению работы сервера.
Более современным и эффективным методом является использование объекта ЧтениеТекста. Этот объект позволяет считывать файл построчно, что значительно экономит ресурсы системы. Выясним, как реализовать чтение файла с его помощью:
&НаСервере
Процедура ЗагрузитьДанныеНаСервере(ПутьКФайлу)
Текст = Новый ЧтениеТекста(ПутьКФайлу, КодировкаТекста.ANSI); // Shoppy часто использует ANSI
СтрокаФайла = Текст.ПрочитатьСтроку();
Пока СтрокаФайла <> Неопределено Цикл
// Здесь будет логика обработки каждой строки
ОбработатьСтрокуДанных(СтрокаФайла);
СтрокаФайла = Текст.ПрочитатьСтроку();
КонецЦикла;
Текст.Закрыть();
КонецПроцедуры
Текстовые файлы из кассовых программ обычно имеют структуру с разделителями (например, точка с запятой или вертикальная черта). Нам нужно извлечь из строки конкретные значения: код магазина, дату и код операции. Для этого идеально подходит функция СтрРазделить.
Рассмотрим пример, где в строке данные идут в следующем порядке: Дата;КодМагазина;КодОперации;Артикул;Количество;Сумма. Проанализируем, как выделить нужные нам позиции:
Процедура ОбработатьСтрокуДанных(Строка)
МассивДанных = СтрРазделить(Строка, ";");
// Проверяем, что в строке достаточно данных
Если МассивДанных.Количество() < 3 Тогда
Возврат;
КонецЕсли;
ДатаИзФайла = МассивДанных[0];
КодМагазина = МассивДанных[1];
КодОперации = МассивДанных[2];
// Выполняем выборку (фильтрацию)
// Например, нас интересуют только продажи (код 1) по конкретному магазину
Если КодМагазина = "001" И КодОперации = "1" Тогда
// Продолжаем обработку: поиск номенклатуры и создание документа
СоздатьЗаписьОПродаже(МассивДанных);
КонецЕсли;
КонецПроцедуры
Просто прочитать код из файла недостаточно. Система 1С работает со ссылочными типами данных. Нам нужно найти соответствующие элементы в справочниках Склады и Номенклатура. Рекомендуется использовать поиск по коду или артикулу, так как наименования могут отличаться.
Разберем, как реализовать поиск склада по коду магазина, пришедшему из Shoppy:
Функция НайтиСкладПоКоду(КодМагазина)
СкладСсылка = Справочники.Склады.НайтиПоКоду(КодМагазина);
Если СкладСсылка.Пустая() Тогда
// Можно записать ошибку в лог или создать склад автоматически
ЗаписьЖурналаРегистрации("ЗагрузкаДанных", УровеньЖурналаРегистрации.Ошибка, , , "Склад не найден: " + КодМагазина);
КонецЕсли;
Возврат СкладСсылка;
КонецФункции
В 1С:Бухгалтерия 3.0 результаты розничной торговли фиксируются документом ОтчетОРозничныхПродажах. Поскольку в текстовом файле может быть множество строк по одной смене, правильно будет сначала собрать все данные в таблицу значений, сгруппировать их по товарам, а затем создать один итоговый документ.
Важный момент: использование транзакций. Проанализируем ситуацию: если в процессе создания документа из 100 строк на 99-й произойдет ошибка (например, не заполнена цена), то без транзакции в базе останется "битый" документ. Использование НачатьТранзакцию() и ЗафиксироватьТранзакцию() гарантирует, что либо загрузятся все данные, либо ни одного.
НачатьТранзакцию();
Попытка
НовыйДокумент = Документы.ОтчетОРозничныхПродажах.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Склад = СкладСсылка;
// Заполнение табличной части Товары...
НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Ошибка при записи документа: " + ОписаниеОшибки());
КонецПопытки;
В исходном вопросе упоминалось, что файл выгружается на FTP-сервер. Чтобы избавить пользователя от ручного скачивания, мы можем добавить в нашу кнопку логику работы с объектом FTPСоединение. Программа сама подключится к серверу, найдет файл по маске (например, sales_*.txt) и скачает его во временный каталог перед обработкой.
Для реализации этого механизма используем следующий алгоритм:
FTPСоединение, указывая адрес, порт, логин и пароль.ПолучитьФайлы() для загрузки данных во временную папку пользователя через КаталогВременныхФайлов().УдалитьФайлы() на FTP, чтобы не обрабатывать один и тот же отчет дважды.Мы рассмотрели полный цикл создания кнопки "Выполнить выгрузку". Основные выводы, которые помогут сделать вашу обработку надежной:
ЧтениеТекста для работы с файлами любого объема.СтрРазделить для быстрого доступа к полям строки.Следование этим рекомендациям позволит создать профессиональный инструмент интеграции, который минимизирует ручной ввод данных и исключит ошибки человеческого фактора при переносе продаж из системы Shoppy в 1С:Бухгалтерия.