Здравствуйте, уважаемые.
Сразу отмечу, что в данной статье речь пойдет больше про работу с 1С: ERP, но в целом, может подойти для любого решения на базе 1С.
Суть проблемы
Итак, я работаю на крупном заводе, у нас развёрнута 1С:ERP, в которой ведётся производственный блок.
Также имеются программы ЗУП и Бухгалтерия 3.0, но уже отдельными информационными базами.
Также имеются сторонние программы а именно SOLVO и PREAKTOR, и ещё несколько менее важных систем.
Зачем я всё так подробно расписываю? - Дело в том, что производство в частности, и любой более менее крупный проект, он, как правило, инкапсулирует в себе несколько решений/блоков/систем/информационных баз. Всё это накладывает определенные ограничения и вытекающие из них последствия. Я говорю, в частности, про синхронизацию.
У нас на предприятии производство ведется в блоке SOLVO, и выгрузка из него попадает в 1С:Предприятие.
Обеспечивается она с помощью регламентного задания, которое запускается раз в 5 минут, и забирает данные из SOLVO.
Далее пишет их в ERP. - Данный обмен крайне важен для производственного блока, и его прерывание грозит серьезными последствиями.
+ Важно решать проблему с обменом в кратчайшие сроки, т.к. завод крупный, постоянно идёт сборка и отгрузка товара.
В связи с чем, данный обмен всегда был под повышенным вниманием, что понятно.
С моей стороны велась доработка и улучшение блока, чтобы он как можно реже "ломался", но практика показала, что даже при более-менее идеальных условиях прохода данных через обмен, всё равно возникают нештатные ситуации.
О чем речь:
- Человеческий фактор
- Сбой на стороне ПО
- Внешний сбой - падение электричества
- Отключение интернета
Резюмируя, можно сказать следующее, что идеально "заточить" систему так, чтоб данный блок отрабатывал на 100%, невозможно. В связи с чем, я пришел к выводу о том, что нужно подойти к решению с другой стороны.
Решение
Т.к. физически исправить ситуацию не реально, я решил установить какую-то систему оповещения об ошибках. Уведомления из 1С или что-то типа того. Т.е. мысль следующая: когда возникает ошибка, - я должен об этом узнать в максимально сжатые сроки. Т.к. "встать" обмен может и ночью.
"Прошерстив" интернет и не особо найдя ответы, я набрёл на методы решения в виде интеграторов ботов от Watsapp и Telegram. - это пожалуй ближе всего подходило к моей теме, но вскоре я понял, что настраивать эти системы не хочется от слова "совсем".
Все же мне повезло, когда появилась программа MIE (не путать с гладильными системами).
Итак, как она мне помогла и чего я смог добиться.
Во-первых, данное ПО предоставляет ограниченный набор функций, все из них я представлю в коде ниже:
//БАЗОВЫЕ ФУНКИИ *********************************
//СформироватьNotificationMessage - отправляет письмо на телефон по ключевым параметрам.
//в функции мы указываем кому отрпавяем, что отправляем, и связка по idОганизации и паролю.
///////
//Если пользователь в базе то вернёт дату окончания подписки в виде текста
//иначе вернёт: "client not found"
//
Функция ВернутьДатуОкончанияПодписки(idОрганизации,idПользователя) Экспорт
ТекстП =СтрШаблон("/PROJ/projMIE/MIE_getClient.php?Org=%1&Client=%2",
КодирURL(idОрганизации), КодирURL(idПользователя) );
Возврат ОтправитьGetЗапрос(ТекстП );
КонецФункции
//idОрганизации(20симв.),idПользователя(40симв.),passwordОрганизации(10симв.) - это ключевые параметры.
//НазваниеПисьма - 30симв.
//ТекстПисьма - 60симв.
//ВажностьПисьма: 0-просто сообщение. будет отражаться в программе.
// 1-важное. придет как Notification один раз.
// 2-срочное. придет как Notification до тех пор пока не будет запущенна программа на тел.
//
Процедура СформироватьNotificationMessage(idОрганизации,idПользователя,passwordОрганизации,НазваниеПисьма,ТекстПисьма,ВажностьПисьма) Экспорт
ТекстП =СтрШаблон("/PROJ/projMIE/MIE_add.php?Name=%1&Text=%2&vaznost=%3&id_org=%4&pass_org=%5&Client=%6",
КодирURL(НазваниеПисьма),КодирURL(ТекстПисьма), КодирURL(ВажностьПисьма), КодирURL(idОрганизации) , КодирURL(passwordОрганизации) , КодирURL(idПользователя)
);
ОтправитьGetЗапрос(ТекстП);
КонецПроцедуры
//idОрганизации(20симв.),idПользователя(40симв.)- это ключевые параметры.
//ЗаголовокКEvants-30симв.
//
Процедура ЗаголовокEvents(idОрганизации,idПользователя,ЗаголовокКEvants) Экспорт
ТекстП =СтрШаблон("/PROJ/projMIE/MIE_add5.php?Org=%1&Client=%2&NameZagolovok=%3&var=0",
КодирURL(idОрганизации), КодирURL(idПользователя), КодирURL(ЗаголовокКEvants) );
ОтправитьGetЗапрос(ТекстП);
Конецпроцедуры
//idОрганизации(20симв.),idПользователя(40симв.),passwordОрганизации(10симв.) - это ключевые параметры.
//
Процедура ОчиститьEvents(idОрганизации,idПользователя,passwordОрганизации) Экспорт
ТекстП =СтрШаблон("/PROJ/projMIE/MIE_addEventClear.php?id_org=%1&pass_org=%2&Client=%3",
КодирURL(idОрганизации), КодирURL(passwordОрганизации), КодирURL(idПользователя) );
ОтправитьGetЗапрос(ТекстП);
Конецпроцедуры
//idОрганизации(20симв.),idПользователя(40симв.),passwordОрганизации(10симв.) - это ключевык параметры.
//НомерСч от 0 до 9. Всего 10 событий
//Название-название События. (80симв)
//Значение-значение события. (140симв.)
//
Процедура СформироватьEvents(idОрганизации,idПользователя,passwordОрганизации,НомерСч,Название,Значение) Экспорт
ТекстП =СтрШаблон("/PROJ/projMIE/MIE_addEvent.php?id_org=%1&pass_org=%2&Client=%3&Nomer=%4&Name=%5&Zna4=%6",
КодирURL(idОрганизации), КодирURL(passwordОрганизации), КодирURL(idПользователя), КодирURL(НомерСч) , КодирURL(Название) , КодирURL(Значение)
);
ОтправитьGetЗапрос(ТекстП);
Конецпроцедуры
//idОрганизации(20симв.),idПользователя(40симв.),passwordОрганизации(10симв.) - это ключевык параметры.
//ДвоичныеДанныеФайла - ДвоичныеДанные до 2х мег.
//НазваниеФайлаВПриложении (30 симв)
//Отчёт отправялется в "htm" формате!
//
Процедура ДобавитьОтчет(idОрганизации,idПользователя,passwordОрганизации,ДвоичныеДанныеФайла,НазваниеФайлаВПриложении)
WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
Boundary = "00000000000000";
ФайлДанных = "uploadedFile.htm";
РазделительСтрок = Символ(10)+Символ(13);
Зп = "--" + Boundary + "
|Content-Disposition: form-data; name=""data""; filename=""" + ФайлДанных + """
|Content-Type: application/xml;" + РазделительСтрок + РазделительСтрок + "
|" + ДвоичныеДанныеФайла + РазделительСтрок + "
|--" + Boundary + "--";
WinHttp.Open("POST","https://lykurgsoftware.ru/PROJ/projMIE/upload.php", 0);
WinHttp.SetRequestHeader("Content-Type","multipart/form-data;boundary=" + Boundary);
WinHttp.SetRequestHeader("Content-Length", СтрДлина(Зп));
WinHttp.SetRequestHeader("NameF",КодирURL(НазваниеФайлаВПриложении));
WinHttp.SetRequestHeader("Client",КодирURL(idПользователя));
WinHttp.SetRequestHeader("idOrganization",КодирURL(idОрганизации));
WinHttp.SetRequestHeader("passOrganization",КодирURL(passwordОрганизации));
WinHttp.Send(Зп);
Если WinHttp.Status = 200 Тогда
Рез = WinHttp.ResponseText;
Если Рез ="ok" Тогда Сообщить("Запись прошла успешно");
ИначеЕсли Рез ="-2" Тогда Сообщить("Пароль не верный");
ИначеЕсли Рез ="-3" Тогда Сообщить("Не верная организация");
ИначеЕсли Рез ="-4" Тогда Сообщить("Файл превышает лиммит по объёму");
ИначеЕсли Рез ="-5" Тогда Сообщить("Не верный формат файла");
ИначеЕсли Рез ="-6" Тогда Сообщить("Возможно не заведён(не верно заведён) пользователь либо организация. Либо это ошибка потока.");
ИначеЕсли Рез ="-20" Тогда Сообщить("Период использования приложения закончился");
Иначе Сообщить("Неизвестная ошибка "+Рез);
КонецЕсли;
Иначе сообщить("Проверьте доступ в интернет. "+WinHttp.ResponseText);
КонецЕсли;
КонецПроцедуры
Для решения моей основной задачи мне потребовалась всего одна ф-я: СформироватьNotificationMessage
В которую я передал данные из своей системы.
Суть реализации следующая.
1) Устанавливается мобильное приложение на телефон. Например, тут: MIE
2) Настраивается (достаточно быстро).
3) Проверяется связь 1С- приложение.
4) Из 1С запускается нужная функция.
5) Получаем уведомление в телефон.
И всё. Т.е реализация крайне проста. Суть приложения в том, что на телефон приходит push-уведомление от 1С. Со звуковым сигналом. Также есть возможность вызова "срочных" уведомлений. Т.е. ваш телефон будет названивать до тех пор, пока вы не обратите внимание на проблему.
Итак, моя реализация:
Вот рабочий код из ERP, который использует данный функционал
//Оповещение (MIE) *********
Разница =(Текущаядата()-ВремяПоследнегоЗадания)/60;
Если Разница > 10 Тогда
РТК_СлужебныйНаСервере.СформироватьNotificationMessage("Завод***","ХорошулинАВ","6655","Задание: РегЗадание_5мин", "Важно! рег задание простаивает уже на: "+строка(Окр(Разница,2))+"мин.",0);
КонецЕсли;
Если Разница > 30 Тогда
РТК_СлужебныйНаСервере.СформироватьNotificationMessage("Завод***","ХорошулинАВ","6655","Задание: РегЗадание_5мин", "Важно! рег задание простаивает уже на: "+строка(Окр(Разница,2))+"мин.",2);
КонецЕсли;
//**********
ЗаголовокEvents("Завод***","ХорошулинАВ","Открытые смены на:"+Строка(Лев(Текущаядата(),10)));
РТК_СлужебныйНаСервере.ОчиститьEvents("Завод***","ХорошулинАВ","6655");
ТЗ = РТК_СлужебныйНаСервере.ВернутьТЗЗапроса( "ВЫБРАТЬ
| evp_СменноеЗадание.Ссылка КАК Смена,
| evp_СменноеЗадание.Подразделение КАК Подразделение
|ИЗ
| Документ.evp_СменноеЗадание КАК evp_СменноеЗадание
|ГДЕ
| evp_СменноеЗадание.СостояниеСмены = ЗНАЧЕНИЕ(Перечисление.evp_СостоянияСмены.Открыта)
| И evp_СменноеЗадание.Подразделение.Наименование <> ""Отдел снабжения""
| И evp_СменноеЗадание.Подразделение.Наименование <> ""Отдел продаж укупорочной продукции""
| И evp_СменноеЗадание.Подразделение.Наименование <> ""Производственная площадка""
| И evp_СменноеЗадание.Подразделение.Наименование <> "" Цех №5""
|
|УПОРЯДОЧИТЬ ПО
| evp_СменноеЗадание.Дата УБЫВ");
Сч_событий=0;
Для каждого стр Из ТЗ Цикл Сч_событий=Сч_событий+1;
РТК_СлужебныйНаСервере.СформироватьEvents("Завод***","ХорошулинАВ","6655",Сч_событий,"По подразделению: "+строка(стр.Подразделение),стр.Смена);
Если Сч_событий>=10 тогда прервать; КонецЕсли;
КонецЦикла;
//**************************************
Т.е. я отлавливаю факт того, что обмен не проходит больше 30 минут!! Для меня это очень важное событие!
Я отправляю сообщение которое приходит мне на телефон. Теперь я всегда в курсе, держу руку на пульсе, так сказать.
Слежу за важными блоками системы практически в реальном времени.
Что еще может эта программа?
Также я использовал функции по переносу данных о "не закрытых сменах".
Так как у нас производство, цеха работают посменно - важно, чтобы смена закрывалась без проблем. Если она не закрыта вовремя - значит, случилась проблема. Все эти моменты также важны, и их также можно передать из 1С в телефон.
Т.е. буквально грузится список всех незакрытых смен, что видно из кода выше. Данные можно анализировать в телефоне с разницей в 5 минут.
Ну и последняя "плюшка", которую я лично не использовал, но которая есть, - это отчёты. Т.е любой отчет в виде табличного документа сохраняется в двоичные данные и вскоре оказывается в мобильном приложении. Думаю, это удобно.
Коллеги, всем удачи, всем успехов, будьте бдительны, заботьтесь о своём 1С обеспечении, и будьте в курсе событий, которые происходят в нём. Спасибо за интерес к статье!
Тестировалось на версии:
1С:Предприятие 8.3 (8.3.22.1923)
Конфигурация: 1С:ERP Управление предприятием
БИТ.ФИНАНС 3.2
Copyright © 2009 - 2018, ООО "БТ". Все права защищены. (2.4.3.137/3.2.20.4) (http://v8.1c.ru/erp/)
Copyright © ООО "1C-Софт", 2004-2018. Все права защищены (http://www.1c.ru)