#Область ОбработчикиСобытийФормы
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ЗаполнитьЗначенияСвойств(ЭтотОбъект, Параметры, "НомерЧека, СсылкаНаЧек, ЧекСамозанятого");
ДокументВладелец = Параметры.РасходныйДокумент;
Если Не ЗначениеЗаполнено(ДокументВладелец) Тогда
ОбщегоНазначения.СообщитьПользователю(НСтр("ru = 'Перед загрузкой чека запишите документ'"), , , ,Отказ);
Возврат;
КонецЕсли;
МетаданныеВладельца = ДокументВладелец.Метаданные();
Если Не ПравоДоступа("Изменение", МетаданныеВладельца) Тогда
ТолькоПросмотр = Истина;
Элементы.ГруппаОчиститьЗагрузить.Видимость = Ложь;
КонецЕсли;
ПредыдущееЗначениеСсылкиНаЧек = "";
ВывестиКартинку(АдресКартинки, ЧекСамозанятого);
УправлениеФормой(ЭтотОбъект);
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если ЗначениеЗаполнено(СсылкаНаЧек) Тогда
СсылкаНаЧекПриИзменении("");
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытийЭлементовШапкиФормы
&НаКлиенте
Процедура СсылкаНаЧекПриИзменении(Элемент)
Если СсылкаНаЧек = ПредыдущееЗначениеСсылкиНаЧек Тогда
Возврат;
КонецЕсли;
ПредыдущееЗначениеСсылкиНаЧек = СсылкаНаЧек;
АдресСервисаМойНалог = "https://lknpd.nalog.ru";
Если СтрНайти(СсылкаНаЧек, АдресСервисаМойНалог) = 0 Тогда
// Это не ссылка на чек, поэтому ничего не делаем
Возврат;
КонецЕсли;
ПолучитьДанныеПоСсылкеНаЧек();
УправлениеФормой(ЭтотОбъект);
КонецПроцедуры
&НаКлиенте
Процедура АдресКартинкиНажатие(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Если Не ЗначениеЗаполнено(АдресКартинки) Тогда
ОписаниеОповещения = Новый ОписаниеОповещения("ДобавлениеЧекаСамозанятогоЗавершение", ЭтотОбъект);
РаботаСФайламиКлиент.ДобавитьФайл(ОписаниеОповещения, ДокументВладелец, ЭтотОбъект, 2);
Иначе
ДанныеФайла = ДанныеФайла(ЧекСамозанятого, УникальныйИдентификатор);
РаботаСФайламиКлиент.ОткрытьФайл(ДанныеФайла);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ОчиститьЧекНажатие(Элемент)
СсылкаНаЧек = "";
НомерЧека = "";
АдресКартинки = "";
ПредыдущееЗначениеСсылкиНаЧек = "";
ЧекБылОчищен = Истина;
УправлениеФормой(ЭтотОбъект);
КонецПроцедуры
&НаКлиенте
Процедура ЗагрузитьЧекНажатие(Элемент)
ОписаниеОповещения = Новый ОписаниеОповещения("ДобавлениеЧекаСамозанятогоЗавершение", ЭтотОбъект);
РаботаСФайламиКлиент.ДобавитьФайл(ОписаниеОповещения, ДокументВладелец, ЭтотОбъект, 2);
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиКомандФормы
&НаКлиенте
Процедура ПерейтиПоСсылке(Команда)
Если ЗначениеЗаполнено(СсылкаНаЧек) Тогда
ПерейтиПоНавигационнойСсылке(СсылкаНаЧек);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура КомандаОК(Команда)
Структура = Новый Структура;
Структура.Вставить("СсылкаНаЧек", СсылкаНаЧек);
Структура.Вставить("НомерЧека", НомерЧека);
Если Не ЗначениеЗаполнено(АдресКартинки) Тогда
Структура.Вставить("ЧекСамозанятого", Неопределено);
Иначе
Структура.Вставить("ЧекСамозанятого", ЧекСамозанятого);
КонецЕсли;
Структура.Вставить("ЧекБылОчищен", ЧекБылОчищен);
Закрыть(Структура);
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
&НаКлиенте
Процедура ДобавлениеЧекаСамозанятогоЗавершение(Результат, ДополнительныеПараметры) Экспорт
Если Результат = Неопределено Тогда
Возврат;
КонецЕсли;
ЧекСамозанятого = Результат.ФайлСсылка;
ВывестиКартинку(АдресКартинки, ЧекСамозанятого);
УправлениеФормой(ЭтотОбъект);
КонецПроцедуры
&НаСервере
Процедура ВывестиКартинку(АдресКартинки, Знач ЧекСамозанятого)
Если ЗначениеЗаполнено(ЧекСамозанятого) Тогда
АдресКартинки = РаботаСФайлами.ДанныеФайла(ЧекСамозанятого).СсылкаНаДвоичныеДанныеФайла;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Копия чека была присоединена к документу " + ДокументВладелец;
Сообщение.Сообщить();
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ДанныеФайла(ФайлКартинки, УникальныйИдентификатор)
ДополнительныеПараметры = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
ДополнительныеПараметры.ИдентификаторФормы = УникальныйИдентификатор;
Возврат РаботаСФайлами.ДанныеФайла(ФайлКартинки, ДополнительныеПараметры);
КонецФункции
&НаКлиентеНаСервереБезКонтекста
Процедура УправлениеФормой(Форма)
Элементы = Форма.Элементы;
Элементы.ЗагрузитьЧек.Видимость = Не ЗначениеЗаполнено(Форма.АдресКартинки);
Элементы.ОчиститьЧек.Видимость = ЗначениеЗаполнено(Форма.АдресКартинки);
КонецПроцедуры
&НаСервере
Процедура ПолучитьДанныеПоСсылкеНаЧек()
НомерЧека = ИнтеграцияСПлатформойСамозанятыеБПНомерЧекаИзСсылки(СсылкаНаЧек);
ЧекСамозанятого = ИнтеграцияСПлатформойСамозанятыеБПЧекСамозанятогоИзИнтернета(
СсылкаНаЧек, ЧекСамозанятого, ДокументВладелец);
Если ЗначениеЗаполнено(ЧекСамозанятого) Тогда
ВывестиКартинку(АдресКартинки, ЧекСамозанятого);
Иначе
ТекстСообщения = НСтр("ru='Не удалось скачать чек с сайта ФНС.
|Проверьте ссылку или попробуйте загрузить чек позднее'");
ОбщегоНазначения.СообщитьПользователю(ТекстСообщения, , "СсылкаНаЧек");
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область ИнтеграцияСПлатформойСамозанятые
// Функция возвращает номер чека из ссылки на чек на сайте ФНС
//
// Параметры:
// СсылкаНаЧек - Строка - URL на чек самозанятого на сайте ФНС
//
// Возвращаемое значение:
// Строка - Номер чека
//
&НаСервере
Функция ИнтеграцияСПлатформойСамозанятыеБПНомерЧекаИзСсылки(СсылкаНаЧек) Экспорт
АдресСервисаМойНалог = "https://lknpd.nalog.ru";
ЧастьСсылкиНаЧек = СтрЗаменить(СсылкаНаЧек,АдресСервисаМойНалог, "");
ЧастиСсылки = СтрРазделить(ЧастьСсылкиНаЧек, "/");
ИНН = ИННИзСсылкиНаЧек(ЧастиСсылки);
НомерЧека = "";
ПредыдущееЗначение = "";
СоответствуетУсловиям = Ложь;
// Номер чека идет после ИНН и перед "print"
Для Каждого ЧастьСсылки Из ЧастиСсылки Цикл
Если ЗначениеЗаполнено(НомерЧека) И ЧастьСсылки = "print" Тогда
СоответствуетУсловиям = Истина;
КонецЕсли;
Если ПредыдущееЗначение = ИНН Тогда
НомерЧека = ЧастьСсылки;
КонецЕсли;
ПредыдущееЗначение = ЧастьСсылки;
КонецЦикла;
Если Не СоответствуетУсловиям Тогда
НомерЧека = "";
КонецЕсли;
Возврат НомерЧека;
КонецФункции
// Получает ИНН контрагента из ссылки на чек самозанятого.
//
// Параметры:
// ЧастиСсылки - Массив из Строка - Массив, полученный в результате разделения ссылки на чек по символу "/".
//
// Возвращаемое значение:
// Строка
//
&НаСервере
Функция ИННИзСсылкиНаЧек(ЧастиСсылки) Экспорт
ИНН = "";
Для Каждого ЧастьСсылки Из ЧастиСсылки Цикл
Результат = ИдентификационныеНомераНалогоплательщиковПроверитьСоответствиеТребованиямИНН(ЧастьСсылки, Ложь);
Если Результат.СоответствуетТребованиям Тогда
ИНН = ЧастьСсылки;
Прервать;
КонецЕсли;
КонецЦикла;
Возврат ИНН;
КонецФункции
&НаСервере
Функция ИдентификационныеНомераНалогоплательщиковПроверитьСоответствиеТребованиямИНН(Знач ИНН, Знач ЭтоЮрЛицо) Экспорт
Перем ТекстОшибкиФорматнаяПроверка;
РезультатПроверки = Новый Структура("СоответствуетТребованиям, ЭтоЮрЛицо, ОписаниеОшибки", Истина, ЭтоЮрЛицо, "");
Если ЗначениеЗаполнено(ИНН) Тогда
ИНН = СокрП(ИНН);
ЭтоИННФизическогоЛица = ЭтоИННФизическогоЛица(ИНН);
ЭтоИННЮридическогоЛица = ЭтоИННЮридическогоЛица(ИНН);
Если РезультатПроверки.ЭтоЮрЛицо И НЕ ЭтоИННЮридическогоЛица Тогда
РезультатПроверки.ОписаниеОшибки = НСтр("ru = 'ИНН юридического лица должен состоять из 10 цифр'");
Если ЭтоИННФизическогоЛица Тогда
// Ошибка в определении вида контрагента, однако ИНН может быть все равно корректным - просто надо изменить вид.
РезультатПроверки.ЭтоЮрЛицо = Ложь;
Иначе
РезультатПроверки.СоответствуетТребованиям = Ложь;
КонецЕсли;
ИначеЕсли НЕ РезультатПроверки.ЭтоЮрЛицо И НЕ ЭтоИННФизическогоЛица Тогда
РезультатПроверки.ОписаниеОшибки = НСтр("ru = 'ИНН физического лица должен состоять из 12 цифр'");
Если ЭтоИННЮридическогоЛица Тогда
// Ошибка в определении вида контрагента, однако ИНН может быть все равно корректным - просто надо изменить вид.
РезультатПроверки.ЭтоЮрЛицо = Истина;
Иначе
РезультатПроверки.СоответствуетТребованиям = Ложь;
КонецЕсли;
КонецЕсли;
Если РезультатПроверки.СоответствуетТребованиям Тогда
Если Лев(ИНН, 2) = "00" Тогда
РезультатПроверки.ОписаниеОшибки = НСтр("ru = 'Первые две цифры ИНН не могут быть ""00""'");
РезультатПроверки.СоответствуетТребованиям = Ложь;
Иначе
РезультатПроверки.СоответствуетТребованиям = РегламентированныеДанныеКлиентСервер.ИННСоответствуетТребованиям(ИНН, РезультатПроверки.ЭтоЮрЛицо, ТекстОшибкиФорматнаяПроверка);
Если НЕ РезультатПроверки.СоответствуетТребованиям Тогда
РезультатПроверки.ОписаниеОшибки = ТекстОшибкиФорматнаяПроверка;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Иначе
РезультатПроверки.СоответствуетТребованиям = Ложь;
// В этом случае описание ошибки не выводим,
// так как описание ошибки из этой функции обычно используется для вывода на форме,
// а о незаполненном ИНН на форме сообщаем другими средствами.
КонецЕсли;
Возврат РезультатПроверки;
КонецФункции
&НаСервере
Функция ЭтоИННЮридическогоЛица(ИНН) Экспорт
// ММВ-7-6/435@
// 1. Структура идентификационного номера налогоплательщика (далее - ИНН) представляет собой:
// 1) для организации - десятизначный цифровой код:
Возврат СтрДлина(ИНН) = МинимальнаяДлинаИНН();
КонецФункции
&НаСервере
Функция ЭтоИННФизическогоЛица(ИНН) Экспорт
// ММВ-7-6/435@
// 1. Структура идентификационного номера налогоплательщика (далее - ИНН) представляет собой:
// 2) для физического лица - двенадцатизначный цифровой код:
Возврат СтрДлина(СокрЛП(ИНН)) = МаксимальнаяДлинаИНН();
КонецФункции
&НаСервере
Функция МинимальнаяДлинаИНН() Экспорт
// ММВ-7-6/435@
// 1. Структура идентификационного номера налогоплательщика (далее - ИНН) представляет собой:
// 1) для организации - десятизначный цифровой код:
// 2) для физического лица - двенадцатизначный цифровой код:
Возврат 10;
КонецФункции
&НаСервере
Функция МаксимальнаяДлинаИНН() Экспорт
// ММВ-7-6/435@
// 1. Структура идентификационного номера налогоплательщика (далее - ИНН) представляет собой:
// 1) для организации - десятизначный цифровой код:
// 2) для физического лица - двенадцатизначный цифровой код:
Возврат 12;
КонецФункции
// Функция возвращает ссылку на скаченный файл чека самозанятого по переданной ссылке
//
// Параметры:
// СсылкаНаЧек - Строка - URL на чек самозанятого на сайте ФНС
// ЧекСамозанятого - СправочникСсылка.ВыплатыСамозанятымПрисоединенныеФайлы - Ссылка на присоединенный файл,
// чтобы можно было его обновить
// Документ - ДокументСсылка.ВыплатыСамозанятым, ДокументСсылка.ПоступлениеТоваровУслуг, Документ.ПоступлениеДопРасходов
// - Ссылка на документ, к которому присоединяется файл
//
// Возвращаемое значение:
// СправочникСсылка.ВыплатыСамозанятымПрисоединенныеФайлы, СправочникСсылка.ПоступлениеТоваровУслугПрисоединенныеФайлы,
// Неопределено - Ссылка на присоединенный файл, в случае возникновения ошибки возвращается Неопределено
//
&НаСервере
Функция ИнтеграцияСПлатформойСамозанятыеБПЧекСамозанятогоИзИнтернета(СсылкаНаЧек, ЧекСамозанятого, Документ) Экспорт
URL = СсылкаНаЧек;
ПараметрыПолучения = ПолучениеФайловИзИнтернетаКлиентСервер.ПараметрыПолученияФайла();
ПараметрыПолучения.Таймаут = 1260;
Результат = ПолучениеФайловИзИнтернета.СкачатьФайлВоВременноеХранилище(URL, ПараметрыПолучения);
Если Результат.Статус Тогда
ИмяФайла = СтрШаблон(НСтр("ru='№%1'"), ИнтеграцияСПлатформойСамозанятыеБПНомерЧекаИзСсылки(СсылкаНаЧек));
Если ЗначениеЗаполнено(ЧекСамозанятого) Тогда
// Обновим существующий файл
ИнформацияОФайле = Новый Структура;
ИнформацияОФайле.Вставить("АдресФайлаВоВременномХранилище", Результат.Путь);
ИнформацияОФайле.Вставить("АдресВременногоХранилищаТекста", "");
ИнформацияОФайле.Вставить("ИмяБезРасширения", ИмяФайла);
ИнформацияОФайле.Вставить("Расширение", "jpg");
ИнформацияОФайле.Вставить("ДатаМодификацииУниверсальная", ТекущаяУниверсальнаяДата());
РаботаСФайлами.ОбновитьФайл(ЧекСамозанятого, ИнформацияОФайле);
Иначе
// Добавим новый файл
ПараметрыФайла = РаботаСФайлами.ПараметрыДобавленияФайла("Описание");
ПараметрыФайла.ВладелецФайлов = Документ;
ПараметрыФайла.ИмяБезРасширения = ИмяФайла;
ПараметрыФайла.РасширениеБезТочки = "jpg";
ПараметрыФайла.ВремяИзмененияУниверсальное = ТекущаяУниверсальнаяДата();
ПараметрыФайла.Служебный = Ложь;
ЧекСамозанятого = РаботаСФайлами.ДобавитьФайл(ПараметрыФайла, Результат.Путь);
КонецЕсли;
Возврат ЧекСамозанятого;
Иначе
ТекстОшибки = НСтр("ru = 'Не удалось скачать чек самозанятого.
|Описание: %1
|URL: %2'");
Если Результат.Свойство("КодСостояния") Тогда
ТекстОшибки = ТекстОшибки + Символы.ПС + НСтр("ru = 'Код ошибки: %3'");
ТекстОшибки = СтрШаблон(ТекстОшибки, Результат.СообщениеОбОшибке, URL, Результат.КодСостояния);
Иначе
ТекстОшибки = СтрШаблон(ТекстОшибки, Результат.СообщениеОбОшибке, URL);
КонецЕсли;
ЗаписьЖурналаРегистрации(НСтр("ru = 'Загрузка чеков самозанятых из файла'"), УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
КонецЕсли;
КонецФункции
#КонецОбласти