#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
#Область ОбработчикиСобытий
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
Если СпособУстановкиКурса = Перечисления.СпособыУстановкиКурсаВалюты.РасчетПоФормуле Тогда
ТекстЗапроса =
"ВЫБРАТЬ
| Валюты.Наименование КАК СимвольныйКод
|ИЗ
| Справочник.Валюты КАК Валюты
|ГДЕ
| Валюты.СпособУстановкиКурса = ЗНАЧЕНИЕ(Перечисление.СпособыУстановкиКурсаВалюты.НаценкаНаКурсДругойВалюты)
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| Валюты.Наименование
|ИЗ
| Справочник.Валюты КАК Валюты
|ГДЕ
| Валюты.СпособУстановкиКурса = ЗНАЧЕНИЕ(Перечисление.СпособыУстановкиКурсаВалюты.РасчетПоФормуле)";
Запрос = Новый Запрос(ТекстЗапроса);
ЗависимыеВалюты = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("СимвольныйКод");
Для Каждого Валюта Из ЗависимыеВалюты Цикл
Если СтрНайти(ФормулаРасчетаКурса, Валюта) > 0 Тогда
Отказ = Истина;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ЗначениеЗаполнено(ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ОсновнаяВалюта, "ОсновнаяВалюта")) Тогда
Отказ = Истина;
КонецЕсли;
Если Отказ Тогда
ОбщегоНазначения.СообщитьПользователю(
НСтр("ru = 'Курс валюты можно связать только с курсом независимой валюты.'"));
КонецЕсли;
Если СпособУстановкиКурса <> Перечисления.СпособыУстановкиКурсаВалюты.НаценкаНаКурсДругойВалюты Тогда
ИсключаемыеРеквизиты = Новый Массив;
ИсключаемыеРеквизиты.Добавить("ОсновнаяВалюта");
ИсключаемыеРеквизиты.Добавить("Наценка");
ОбщегоНазначения.УдалитьНепроверяемыеРеквизитыИзМассива(ПроверяемыеРеквизиты, ИсключаемыеРеквизиты);
КонецЕсли;
Если СпособУстановкиКурса <> Перечисления.СпособыУстановкиКурсаВалюты.РасчетПоФормуле Тогда
ИсключаемыеРеквизиты = Новый Массив;
ИсключаемыеРеквизиты.Добавить("ФормулаРасчетаКурса");
ОбщегоНазначения.УдалитьНепроверяемыеРеквизитыИзМассива(ПроверяемыеРеквизиты, ИсключаемыеРеквизиты);
КонецЕсли;
Если Не ЭтоНовый() И СпособУстановкиКурса = Перечисления.СпособыУстановкиКурсаВалюты.НаценкаНаКурсДругойВалюты
И РаботаСКурсамиВалют.СписокЗависимыхВалют(Ссылка).Количество() > 0 Тогда
ОбщегоНазначения.СообщитьПользователю(
НСтр("ru = 'Валюта не может быть подчиненной, так как она является основной для других валют.'"));
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Процедура ПередЗаписью(Отказ)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
КурсЗагружаетсяИзИнтернета = СпособУстановкиКурса = Перечисления.СпособыУстановкиКурсаВалюты.ЗагрузкаИзИнтернета;
КурсЗависитОтДругойВалюты = СпособУстановкиКурса = Перечисления.СпособыУстановкиКурсаВалюты.НаценкаНаКурсДругойВалюты;
КурсРассчитываетсяПоФормуле = СпособУстановкиКурса = Перечисления.СпособыУстановкиКурсаВалюты.РасчетПоФормуле;
Если ЭтоНовый() Тогда
Если КурсЗависитОтДругойВалюты Или КурсРассчитываетсяПоФормуле Тогда
ДополнительныеСвойства.Вставить("ОбновитьКурсы");
КонецЕсли;
ДополнительныеСвойства.Вставить("ЭтоНовый");
ДополнительныеСвойства.Вставить("ЗапланироватьКопированиеКурсовВалюты");
Иначе
ПредыдущиеЗначения = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Ссылка,
"Код,СпособУстановкиКурса,ОсновнаяВалюта,Наценка,ФормулаРасчетаКурса");
ПоменялсяСпособУстановкиКурса = ПредыдущиеЗначения.СпособУстановкиКурса <> СпособУстановкиКурса;
ПоменялсяКодВалюты = ПредыдущиеЗначения.Код <> Код;
ПоменяласьОсновнаяВалюта = ПредыдущиеЗначения.ОсновнаяВалюта <> ОсновнаяВалюта;
ПоменяласьНаценка = ПредыдущиеЗначения.Наценка <> Наценка;
ПоменяласьФормула = ПредыдущиеЗначения.ФормулаРасчетаКурса <> ФормулаРасчетаКурса;
Если (КурсЗависитОтДругойВалюты И (ПоменяласьОсновнаяВалюта Или ПоменяласьНаценка Или ПоменялсяСпособУстановкиКурса))
Или (КурсРассчитываетсяПоФормуле И (ПоменяласьФормула Или ПоменялсяСпособУстановкиКурса)) Тогда
ДополнительныеСвойства.Вставить("ОбновитьКурсы");
КонецЕсли;
Если КурсЗагружаетсяИзИнтернета И (ПоменялсяСпособУстановкиКурса Или ПоменялсяКодВалюты) Тогда
ДополнительныеСвойства.Вставить("ЗапланироватьКопированиеКурсовВалюты");
КонецЕсли;
КонецЕсли;
Если СпособУстановкиКурса <> Перечисления.СпособыУстановкиКурсаВалюты.НаценкаНаКурсДругойВалюты Тогда
ОсновнаяВалюта = Справочники.Валюты.ПустаяСсылка();
Наценка = 0;
КонецЕсли;
Если СпособУстановкиКурса <> Перечисления.СпособыУстановкиКурсаВалюты.РасчетПоФормуле Тогда
ФормулаРасчетаКурса = "";
КонецЕсли;
Если ЗначениеЗаполнено(ФормулаРасчетаКурса) Тогда
Попытка
ПроверитьФормулу(ФормулаРасчетаКурса);
Исключение
ИнформацияОбОшибке = ИнформацияОбОшибке();
Уточнение = ОбщегоНазначенияКлиентСервер.УточнениеИсключения(ИнформацияОбОшибке,
НСтр("ru = 'Не удалось вычислить курс валюты по формуле:'"));
ВызватьИсключение(Уточнение.Текст, Уточнение.Категория, , , ИнформацияОбОшибке);
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Процедура ПриЗаписи(Отказ)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
ОбновитьКурсы = ДополнительныеСвойства.Свойство("ОбновитьКурсы");
ЭтоНовый = ДополнительныеСвойства.Свойство("ЭтоНовый");
ТребуетсяЗаписьКурсов = ОбновитьКурсы Или ЭтоНовый;
ВыполняетсяФоновыйПересчетКурсов = ВыполняетсяФоновыйПересчетКурсов();
Если ТребуетсяЗаписьКурсов И ВыполняетсяФоновыйПересчетКурсов Тогда
ВызватьИсключение НСтр("ru = 'Не удалось записать валюту, так как еще не завершился фоновый пересчет курсов.
|Попробуйте записать валюту позже.'");
КонецЕсли;
Если ОбновитьКурсы Тогда
НачатьФоновоеОбновлениеКурсовВалюты();
ИначеЕсли Не ВыполняетсяФоновыйПересчетКурсов Тогда
РаботаСКурсамиВалют.ПроверитьКорректностьКурсаНа01_01_1980(Ссылка);
КонецЕсли;
Если ДополнительныеСвойства.Свойство("ЗапланироватьКопированиеКурсовВалюты") Тогда
ЗапланироватьКопированиеКурсовВалюты();
КонецЕсли;
КонецПроцедуры
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, ТекстЗаполнения, СтандартнаяОбработка)
Если ДанныеЗаполнения = Неопределено Тогда
СпособУстановкиКурса = Перечисления.СпособыУстановкиКурсаВалюты.РучнойВвод;
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция ВыполняетсяФоновыйПересчетКурсов()
ПараметрыЗадания = Новый Структура;
ПараметрыЗадания.Вставить("Наименование", "РаботаСКурсамиВалют.ОбновитьКурсВалюты");
ПараметрыЗадания.Вставить("Состояние", СостояниеФоновогоЗадания.Активно);
Возврат ОбщегоНазначения.ИнформационнаяБазаФайловая()
И ФоновыеЗадания.ПолучитьФоновыеЗадания(ПараметрыЗадания).Количество() > 0;
КонецФункции
Процедура НачатьФоновоеОбновлениеКурсовВалюты()
ПараметрыВалюты = Новый Структура;
ПараметрыВалюты.Вставить("ОсновнаяВалюта");
ПараметрыВалюты.Вставить("Ссылка");
ПараметрыВалюты.Вставить("Наценка");
ПараметрыВалюты.Вставить("ДополнительныеСвойства");
ПараметрыВалюты.Вставить("ФормулаРасчетаКурса");
ПараметрыВалюты.Вставить("СпособУстановкиКурса");
ПараметрыВалюты.Вставить("ИспользуемыеВалютыПриРасчетеКурса", ИспользуемыеВалютыПриРасчетеКурса());
ЗаполнитьЗначенияСвойств(ПараметрыВалюты, ЭтотОбъект);
ПараметрыЗадания = Новый Структура;
ПараметрыЗадания.Вставить("Валюта", ПараметрыВалюты);
ПараметрыЗадания.Вставить("КодыВалют", Справочники.Валюты.КодыВалют());
Если ОбновлениеИнформационнойБазы.НеобходимоОбновлениеИнформационнойБазы() Тогда
РаботаСКурсамиВалют.ОбновитьКурсВалюты(ПараметрыЗадания, Неопределено);
Возврат;
КонецЕсли;
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(Новый УникальныйИдентификатор);
ПараметрыВыполнения.ОжидатьЗавершение = 0;
Результат = ДлительныеОперации.ВыполнитьВФоне("РаботаСКурсамиВалют.ОбновитьКурсВалюты", ПараметрыЗадания,
ПараметрыВыполнения);
Если Результат.Статус = "Ошибка" Тогда
Уточнение = ОбщегоНазначенияКлиентСервер.УточнениеИсключения(Результат.ИнформацияОбОшибке,
НСтр("ru = 'Не удалось запустить обновление курсов валюты по причине:'"));
ВызватьИсключение(Уточнение.Текст, Уточнение.Категория,,, Результат.ИнформацияОбОшибке);
КонецЕсли;
КонецПроцедуры
Процедура ЗапланироватьКопированиеКурсовВалюты()
Если ОбщегоНазначения.РазделениеВключено() И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Валюты") Тогда
МодульРаботаСКурсамиВалютСлужебный = ОбщегоНазначения.ОбщийМодуль("РаботаСКурсамиВалютСлужебный");
МодульРаботаСКурсамиВалютСлужебный.ЗапланироватьКопированиеКурсовВалюты(ЭтотОбъект);
КонецЕсли;
КонецПроцедуры
Функция ИспользуемыеВалютыПриРасчетеКурса()
Если СпособУстановкиКурса = Перечисления.СпособыУстановкиКурсаВалюты.НаценкаНаКурсДругойВалюты Тогда
Возврат ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(ОсновнаяВалюта);
КонецЕсли;
Если СпособУстановкиКурса <> Перечисления.СпособыУстановкиКурсаВалюты.РасчетПоФормуле Тогда
Возврат Новый Массив;
КонецЕсли;
ТекстЗапроса =
"ВЫБРАТЬ
| Валюты.Ссылка КАК Ссылка
|ИЗ
| Справочник.Валюты КАК Валюты
|ГДЕ
| &ФормулаРасчетаКурса ПОДОБНО ""%"" + Валюты.Наименование + ""%"" СПЕЦСИМВОЛ ""~""
| И Валюты.Наименование <> """"";
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.УстановитьПараметр("ФормулаРасчетаКурса", ФормулаРасчетаКурса);
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
ТекстОшибки = НСтр("ru = 'В формуле должна быть использована хотя бы одна основная валюта.'");
ОбщегоНазначения.СообщитьПользователю(ТекстОшибки,, "Объект.ФормулаРасчетаКурса");
ВызватьИсключение ТекстОшибки;
КонецЕсли;
Возврат РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("Ссылка");
КонецФункции
Процедура ПроверитьФормулу(Формула) Экспорт
КодыВалют = Справочники.Валюты.КодыВалют();
Выражение = Справочники.Валюты.ФорматироватьЧисла(Формула);
Для Каждого Валюта Из КодыВалют Цикл
Выражение = СтрЗаменить(Выражение, Валюта.СимвольныйКод, "1");
КонецЦикла;
ОбщегоНазначения.ВычислитьВБезопасномРежиме(Выражение);
КонецПроцедуры
#КонецОбласти
#Иначе
ВызватьИсключение НСтр("ru = 'Недопустимый вызов объекта на клиенте.'");
#КонецЕсли