конст КЛЮЧ_ЗАДАНИЯ_ЗАГРУЗКИ_КУРСОВ = "RatesLoadTask" @ВПодсистеме исключение ИсключениеЗагрузкиКурсовВалют обз знч Валюта: Валюты.Ссылка ; /** Описание: Загружает курсы валют из справочника Валюты за заданный период Параметры: НачалоПериода - дата начала периода загрузки КонецПериода - дата конца периода загрузки */ @ВПроекте метод ЗагрузитьКурсыВалют(НачалоПериода: Дата, КонецПериода: Дата) знч Событие = новый ОперацияЗагрузкиКурсовВалют( НачалоПериодаЗагрузки = НачалоПериода.Представление(), КонецПериодаЗагрузки = КонецПериода.Представление() ) исп Событие.ЗаписатьНачало() знч МассивВалют = Валюты.ПолучитьВсе() для Валюта из МассивВалют попытка ЗагрузитьКурсыВалюты(Валюта, НачалоПериода, КонецПериода) поймать Искл: ИсключениеЗагрузкиКурсовВалют новый ОшибкаЗагрузкиКурсовВалюты( Валюта = Искл.Валюта.Представление(), ОписаниеОшибки = "%{Искл.Описание}", ХарактерОшибки = ХарактерОшибки.ДляПользователя, Важность = ВажностьСобытияЖурналаСобытий.Высокая ).Записать() выбросить новый ИсключениеВыполнения(Искл.Описание, Искл) ; ; ; /** Описание: Загружает курсы валют из справочника Валюты начиная с последней даты курса и по текущую дату */ @ВПроекте метод ЗагрузитьКурсыВалют() знч ТекущаяДата = Дата.Сейчас() знч Событие = новый ОперацияЗагрузкиКурсовВалют( НачалоПериодаЗагрузки = "", КонецПериодаЗагрузки = ТекущаяДата.Представление() ) исп Событие.ЗаписатьНачало() знч ДатыКурсов = ПолучитьКурсыВалют() для ДатаКурса из ДатыКурсов попытка ЗагрузитьКурсыВалюты(ДатаКурса.Валюта, ДатаКурса.Период == Неопределено ? ТекущаяДата : ДатаКурса.Период, ТекущаяДата) поймать Искл: ИсключениеЗагрузкиКурсовВалют новый ОшибкаЗагрузкиКурсовВалюты( Валюта = Искл.Валюта.Представление(), ОписаниеОшибки = "%{Искл.Описание}", ХарактерОшибки = ХарактерОшибки.ДляПользователя, Важность = ВажностьСобытияЖурналаСобытий.Высокая ).Записать() выбросить новый ИсключениеВыполнения(Искл.Описание) ; ; ; /** Описание: Получение курса валюты на дату Параметры: Валюта - валюта, курс которой требуется получить ДатаКурса - дата, на которую требуется получить курс Возвращает: Структура КурсВалюты или Неопределено, если курс не установлен */ @ВПроекте метод ПолучитьКурсВалюты(Валюта: Валюты.Ссылка, ДатаКурса: Дата): КурсВалюты? знч Запрос = Запрос{ ВЫБРАТЬ КурсыВалютСрезПоследних.Валюта КАК Валюта, КурсыВалютСрезПоследних.Период КАК Период, КурсыВалютСрезПоследних.Курс КАК Курс, КурсыВалютСрезПоследних.Кратность КАК Кратность ЗАПОЛНИТЬ КурсВалюты ИЗ КурсыВалют.СрезПоследних(%ДатаКурса) КАК КурсыВалютСрезПоследних ГДЕ КурсыВалютСрезПоследних.Валюта == %Валюта } возврат Запрос.Выполнить().ЕдинственныйИлиУмолчание() ; /** Описание: Получение курсов валют из справочника Валюты Возвращает: Массив структур КурсВалюты Замечания: Если для валюты не загружен курс, значением поля Период структуры будет Неопределено */ @ВПроекте метод ПолучитьКурсыВалют(): Массив<КурсВалюты> знч Курсы = <КурсВалюты>[] знч Запрос = Запрос{ ВЫБРАТЬ Валюты.Ссылка КАК Валюта, Валюты.Код КАК Код, Курсы.Период.ЗаменитьNull(Неопределено) КАК Период, Курсы.Курс.ЗаменитьNull(0) КАК Курс, Курсы.Кратность.ЗаменитьNull(0) КАК Кратность ИЗ Валюты КАК Валюты ЛЕВОЕ СОЕДИНЕНИЕ КурсыВалют.СрезПоследних() КАК Курсы ПО Валюты.Ссылка == Курсы.Валюта ГДЕ Валюты.Код != %{Валюты.КОД_БАЗОВОЙ_ВАЛЮТЫ} } для СтрокаРезультата из Запрос.Выполнить() знч Курс = новый КурсВалюты( Валюта = СтрокаРезультата.Валюта, Код = СтрокаРезультата.Код, Период = СтрокаРезультата.Период, Курс = СтрокаРезультата.Курс, Кратность = СтрокаРезультата.Кратность ) Курсы.Добавить(Курс) ; возврат Курсы ; /** Описание: Пересчитывает сумму в базовую валюту Параметры: Сумма - сумма, которую требуется пересчитать Валюта - пересчитываемая валюта Возвращает: Сумма, пересчитанная по курсу */ @ВПроекте метод ПересчитатьПоКурсу(Сумма: Число, Валюта: Валюты.Ссылка): Число знч КурсВалюты = ПолучитьКурсВалюты(Валюта, Дата.Сейчас()) если КурсВалюты != Неопределено и КурсВалюты.Кратность != 0 возврат (Сумма * КурсВалюты.Курс / КурсВалюты.Кратность).Округлить(2) иначе возврат 0 ; ; /** Описание: Загружает курсы определенной валюты за заданный период с сайта ЦБ Параметры: ВалютаСсылка - валюта, курсы которой требуется загрузить НачалоПериода - дата начала периода загрузки КонецПериода - дата конца периода загрузки Исключения: ОшибкаЗагрузкиКурсовВалют - если не удалось найти валюту во внешнем справочнике и при других ошибках загрузки Замечания: Идентификатор валюты во внешнем справочнике определяется по коду валюты и сохраняется в поле ВнешнийИдентификатор объекта Валюты */ @ВПодсистеме метод ЗагрузитьКурсыВалюты(ВалютаСсылка: Валюты.Ссылка, НачалоПериода: Дата, КонецПериода: Дата) знч Клиент = КлиентHttp.СБазовымUrl("https://www.cbr.ru/scripts/").СМаксимумомПеренаправлений(0) знч Валюта = ВалютаСсылка.ЗагрузитьОбъект() // Получение идентификатора валюты во внешнем справочнике если Валюта.ВнешнийИдентификатор.Пусто() знч ЗапросСправочникаВалют = Клиент.ЗапросGet("XML_valFull.asp") попытка исп Ответ = ЗапросСправочникаВалют.Выполнить() если Ответ.КодСостояния == 200 знч ЧтениеXml = новый ЧтениеXml(Ответ.Тело, Кодировка = "windows-1251") пер ТекущийИд: Строка пер ЭтоЭлементКода: Булево пока ЧтениеXml.Следующий() если ЧтениеXml.ВидУзла == ВидУзлаXml.НачалоЭлемента и ЧтениеXml.Имя == "Item" ТекущийИд = ЧтениеXml.ЗначениеАтрибутаПоИндексу(0) ; если ЭтоЭлементКода и ЧтениеXml.ВидУзла == ВидУзлаXml.Текст и Валюта.Код == ЧтениеXml.Значение Валюта.ВнешнийИдентификатор = ТекущийИд прервать ; ЭтоЭлементКода = ЧтениеXml.ВидУзла == ВидУзлаXml.НачалоЭлемента и ЧтениеXml.Имя == "ISO_Char_Code" ; иначе выбросить новый ИсключениеЗагрузкиКурсовВалют( "Ошибка при получении внешнего справочника валют. Код %{Ответ.КодСостояния}", ВалютаСсылка) ; поймать Искл: ИсключениеHttp выбросить новый ИсключениеЗагрузкиКурсовВалют("Ошибка при выполнении запроса к сервису курсов валют", ВалютаСсылка, Искл) поймать Искл: ИсключениеЧтенияXml выбросить новый ИсключениеЗагрузкиКурсовВалют("Ошибка при чтении внешнего справочника валют", ВалютаСсылка, Искл) ; если не Валюта.ВнешнийИдентификатор.Пусто() исп КонтекстДоступа.Дополнить(Тип<Валюты.Объект>, [Сущность.Право.Изменение]) Валюта.Записать() иначе выбросить новый ИсключениеЗагрузкиКурсовВалют("Во внешнем справочнике не удалось найти валюту с кодом %{Валюта.Код}", ВалютаСсылка) ; ; // Загрузка курсов валюты знч Url = "XML_dynamic.asp?date_req1=${НачалоПериода|дд/ММ/гггг}&date_req2=${КонецПериода|дд/ММ/гггг}&VAL_NM_RQ=%{Валюта.ВнешнийИдентификатор}" знч ЗапросКурсов = Клиент.ЗапросGet(Url) пер КурсыВалюты = <КурсВалюты>[] попытка исп Ответ = ЗапросКурсов.Выполнить() если Ответ.КодСостояния == 200 знч ЧтениеXml = новый ЧтениеXml(Ответ.Тело, Кодировка = "windows-1251") пер ДатаКурса: Дата? пер Кратность: Число пер ЭтоЭлементКурса: Булево пер ЭтоЭлементКратности: Булево пока ЧтениеXml.Следующий() если ЧтениеXml.ВидУзла == ВидУзлаXml.НачалоЭлемента и ЧтениеXml.Имя == "Record" ДатаКурса = новый Дата(ЧтениеXml.ЗначениеАтрибутаПоИндексу(0)) ; если ЭтоЭлементКратности и ЧтениеXml.ВидУзла == ВидУзлаXml.Текст Кратность = новый Число(ЧтениеXml.Значение) ; если ЭтоЭлементКурса и ЧтениеXml.ВидУзла == ВидУзлаXml.Текст знч Курс = новый Число(ЧтениеXml.Значение.Заменить(",",".")) знч КурсВалюты = новый КурсВалюты( Валюта = ВалютаСсылка, Период = ДатаКурса, Курс = Курс, Кратность = Кратность ) КурсыВалюты.Добавить(КурсВалюты) ; ЭтоЭлементКурса = ЧтениеXml.ВидУзла == ВидУзлаXml.НачалоЭлемента и ЧтениеXml.Имя == "Value" ЭтоЭлементКратности = ЧтениеXml.ВидУзла == ВидУзлаXml.НачалоЭлемента и ЧтениеXml.Имя == "Nominal" ; иначе выбросить новый ИсключениеЗагрузкиКурсовВалют("Ошибка при получении курсов валют. Код %{Ответ.КодСостояния}", ВалютаСсылка) ; поймать Искл: ИсключениеHttp выбросить новый ИсключениеЗагрузкиКурсовВалют("Ошибка при выполнении запроса к сервису курсов валют", ВалютаСсылка, Искл) поймать Искл: ИсключениеЧтенияXml выбросить новый ИсключениеЗагрузкиКурсовВалют("Ошибка при чтении курсов валют", ВалютаСсылка, Искл) ; // Запись полученных данных в регистр сведений если не КурсыВалюты.Пусто() для КурсВалюты из КурсыВалюты знч НоваяЗапись = новый КурсыВалют.Запись( Период = КурсВалюты.Период, Валюта = ВалютаСсылка, Курс = КурсВалюты.Курс, Кратность = КурсВалюты.Кратность ) КурсыВалют.Записать(НоваяЗапись) ; ; ; @ВПроекте метод ЗапланироватьЗагрузкуКурсовВалют() ЗапланированныеЗадания.Создать(&КурсыВалютСервер.ЗагрузитьКурсыВалют) .Настроить(Ключ = КЛЮЧ_ЗАДАНИЯ_ЗАГРУЗКИ_КУРСОВ, СтратегияПубликации = СтратегияПубликацииЗадания.Отбросить, Расписание = Расписание.Ежедневно(ЗапуститьВ = Время{12:00}, ИсполнятьПропущенное = Истина), Описание = "Загрузка курсов валют") .ЗапланироватьБезТранзакции() ; @ВПодсистеме метод ПриостановитьЗагрузкуКурсовВалют() ЗапланированныеЗадания.Приостановить(КЛЮЧ_ЗАДАНИЯ_ЗАГРУЗКИ_КУРСОВ) ; @ВПодсистеме метод ВозобновитьЗагрузкуКурсовВалют() если ЗапланированныеЗадания.Возобновить(КЛЮЧ_ЗАДАНИЯ_ЗАГРУЗКИ_КУРСОВ) == Неопределено ЗапланироватьЗагрузкуКурсовВалют() ; ; @ВПодсистеме метод ЗагрузкаКурсовВалютЗапланирована(): Булево знч Дескриптор = ЗапланированныеЗадания.ПолучитьПоКлючу(КЛЮЧ_ЗАДАНИЯ_ЗАГРУЗКИ_КУРСОВ) если Дескриптор != Неопределено возврат Дескриптор.Статус == СтатусЗадания.Ожидает или Дескриптор.Статус == СтатусЗадания.Выполняется иначе возврат Ложь ; ;