в домашних условиях

Диаграммы в 1С83, получение курсов валют по JSON

Категория: SEO,Технологии — Метки: , , Автор: @ 1:48 пп04.11.2020

Описание задачи

Представить в 1С8.3 актуальную информацию об основных курсах в графическом виде.

Реализация

Кратко:

  • платформа разработки 1С8.3, управляемые формы
  • информацию обновляем с сайта НБУ при запуске 1С
  • список валют храним в справочнике, а курсы на дату в регистре сведений
  • настраиваемые графики отображаем при запуске 1С

А теперь подробнее.

Для получения актуальной информации о курсах воспользуемся API предоставленной сайтом НБУ «Офіційний курс гривні до іноземних валют та облікова ціна банківських металів».
Данные будем забирать в формате JSON*.
Ссылка на данные имеет вид https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?date=yyyymmdd&json , где yyyy – год, mm – месяц, dd – день.

*JSON (JavaScript Object Notation) это текстовый формат обмена данными, широко используемый в веб-приложениях

Для хранения полученных с сайта курсов будем использовать Регистр Сведений «КурсВалют». Изменять будем обработкой, поэтому Режим записинезависимый. Периодичностьв пределах дня. ИзмерениеВалюта, РесурсыКурс и Кратность.

Регистр Курсы 1С8.3

Регистр Курсы 1С8.3

В Справочнике «Валюты» будет хранится список валют, присутствующих в выгрузке. Добавим единственный реквизит Наименование полное. В поле Код будем хранить цифровой код валюты, в Наименовании – буквенный код. Для удобства использования нужно создать Форму выбора.

Справочник Валюты 1С8.3

Справочник Валюты 1С8.3

Загружать данные будем обработкой «ПолучениеКурсаВалют».

Добавим возможность делать это за указанный период времени. Для этого на форму добавим два новых реквизита НачалоПериода и КонецПериода.

Модуль Формы содержит следующий код:

//Преобразование разноформатных курсов с сайта к единому формату, четыре знака после запятой. 
//Возвращает пересчитанный курс и его кратность
&НаСервере
Функция ПосчитатьКурсКратность(Курс,Кратность=0)
	Значен = Курс;
	Дробь = Значен - Цел(Значен);
	Разрядность = СтрДлина(Дробь) - 2;
	
	Если Разрядность < 5 Тогда
		Разрядность = 0;
	Иначе
		Разрядность  = Разрядность - 4;
	КонецЕсли; 
	
	Кратность = Pow(10,Разрядность);
	Курс = Значен*Кратность;
	
	Возврат 1;
КонецФункции

&НаСервере
Процедура ПрочитатьССайта(НаДату)
	//Чтение данных в формате JSON штатными средствами 1С8
	ЧтениеJSON = Новый ЧтениеJSON(); 
	ЧтениеJSON.ОткрытьФайл("https://bank.gov.ua/NBUStatService/v1/statdirectory/exchange?"+НаДату+"json"); 
	Валюты = ПрочитатьJSON(ЧтениеJSON); 
	ЧтениеJSON.Закрыть();
	
	//Обработка полученных данных
	Для каждого Валюта из Валюты Цикл
		ВалютаКод	= Валюта.r030; 
		ВалютаНазва	= Валюта.txt; 
		ВалютаКурс	= Валюта.rate; 
		ВалютаТекст	= Валюта.cc; 
		ДатаКурса	= Валюта.exchangedate; 
		 
		//Поиск текущей валюты в справочнике и её создание в случае необходимости
		Валюта = Справочники.Валюты.НайтиПоНаименованию(ВалютаТекст);
		Если Валюта.Пустая() тогда
			НоваяВалюта = Справочники.Валюты.СоздатьЭлемент();
			НоваяВалюта.Код = ВалютаКод;
			НоваяВалюта.Наименование = ВалютаТекст;
			НоваяВалюта.НаименованиеПолное = ВалютаНазва;
			НоваяВалюта.Записать();
			Валюта = НоваяВалюта.Ссылка;
		КонецЕсли;	 
		
		//приведение курса и кратности к единому формату, четыре знака после запятой
		КурсТек=ВалютаКурс; КратностьТек=0;
		ПосчитатьКурсКратность(КурсТек,КратностьТек);
		
		//запись курса в регистр сведений
		Курс = РегистрыСведений.КурсыВалют.СоздатьМенеджерЗаписи();
		Курс.Период = Дата(Прав(ДатаКурса,4),Сред(ДатаКурса,4,5),Лев(ДатаКурса,2));
		Курс.Валюта = Валюта;
		Курс.Курс = КурсТек;
		Курс.Кратность=КратностьТек;
		Курс.Записать();
		 
	КонецЦикла;
КонецПроцедуры


&НаКлиенте
Процедура ПрочитатьКурс(Команда)
	ПустаяДата = '00010101000000';
	//ТекущаяДата
	ТекущаяДата = СервисныеФункции.ПолучитьДатуСервера();
	//Проверка на незаполненные даты периода загрузки курсов
	Если Объект.НачалоПериода = ПустаяДата И Объект.КонецПериода = ПустаяДата тогда
		Объект.НачалоПериода = ТекущаяДата;
		Объект.КонецПериода = ТекущаяДата;
	ИначеЕсли Объект.НачалоПериода = ПустаяДата тогда
		Объект.НачалоПериода = Объект.КонецПериода;
	ИначеЕсли Объект.КонецПериода = ПустаяДата тогда
		Объект.КонецПериода = Объект.НачалоПериода;
	КонецЕсли;	
		
	//Проверка на корректность заполнения периода загрузки курсов
	Если Объект.КонецПериода > ТекущаяДата тогда
		Объект.КонецПериода = ТекущаяДата;
	КонецЕсли;	
	Если Объект.НачалоПериода > ТекущаяДата тогда
		Объект.НачалоПериода = ТекущаяДата;
	КонецЕсли;	
	Если Объект.КонецПериода < Объект.НачалоПериода тогда
		Объект.КонецПериода = Объект.НачалоПериода;
	КонецЕсли;	
	
	//Подготовка форматной строки и передача её в процедуру получения данных
	Для сч = 0 по (НачалоДня(Объект.КонецПериода) - НачалоДня(Объект.НачалоПериода))/24/60/60 цикл
	ПрочитатьССайта("date="+Формат(Объект.НачалоПериода+сч*24*60*60,"ДФ=""ггггММдд""")+"&");
	КонецЦикла	
КонецПроцедуры

//Позволяет запускать обработку из других с переданными параметрами
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
	Если Параметры.Свойство("Отбор") тогда
		Интервал = Параметры.Отбор;
		Объект.НачалоПериода = Интервал.НачДата;
		Объект.КонецПериода = Интервал.КонДата;
		Для сч = 0 по (НачалоДня(Объект.КонецПериода) - НачалоДня(Объект.НачалоПериода))/24/60/60 цикл
ПрочитатьССайта("date="+Формат(Объект.НачалоПериода+сч*24*60*60,"ДФ=""ггггММдд""")+"&");
		КонецЦикла;
		Отказ = Истина;
	КонецЕсли;
КонецПроцедуры

Обработка «ПолучениеКурсаВалют» поденно считывает курсы с сайта НБУ за период, преобразовывает к формату, удобному для хранения и записывает в регистр сведений. Существует возможность вызова этой обработки из другой с определенными параметрами для возможности автоматического обновления курсов.

Для удобства использования вынесем функцию получения текущей даты в Общий модуль СервисныеФункции. В свойствах модуля галочки на Клиент, Сервер, Внешнее соединение.

Сама функция:

Функция ПолучитьДатуСервера() Экспорт
     Возврат ТекущаяДата();
 КонецФункции

Для визуализации информации о курсах воспользуемся формой отчета Графики, на которую выведем четыре реквизита(График1,..График4) с типом Диаграмма.

Форма отчета 1С8.3

Форма отчета 1С8.3

Добавим команды контекстного меню для каждого графика. И кнопку Обновить на форму отчета.

Форма отчета графики 1С8.3

Форма отчета графики 1С8.3

Код модуля формы следующий:

&НаСервереБезКонтекста
Функция ПолучитьТекушийСостав(Имя)
	ТекГраф = Число(Прав(Имя,1));
	
	Запрос = Новый Запрос;
	Запрос.Текст = "
	|Выбрать
	|	Графики.Валюта как Валюта,
	|	Графики.График как График 
	|ИЗ РегистрСведений.ГрафикиОсновнойФормы Как Графики
	|ГДЕ Графики.График = &ТекГрафик
	|";
	
	Запрос.УстановитьПараметр("ТекГрафик",ТекГраф);
	СписокВалют = Новый СписокЗначений;
	
	Рез = Запрос.Выполнить();
	Если НЕ Рез.Пустой() тогда
		Выборка = Рез.Выбрать();
		Пока Выборка.Следующий() цикл
			СписокВалют.Добавить(Выборка.Валюта);				
		КонецЦикла;
	КонецЕсли;	
	
	Возврат СписокВалют;
	
КонецФункции

&НаСервере
Процедура ПостроениеГрафика()
	Запрос = Новый Запрос;
	Запрос.Текст = "
	|ВЫБРАТЬ
	|	КурсыВалют.Период КАК Период,
	|	КурсыВалют.Валюта КАК Валюта,
	|	КурсыВалют.Курс КАК КурсЗ,
	|	КурсыВалют.Кратность КАК Кратность,
	|	КурсыВалют.Курс / КурсыВалют.Кратность КАК Курс
	|ИЗ
	|	РегистрСведений.КурсыВалют КАК КурсыВалют
	|ГДЕ
	|	КурсыВалют.Период МЕЖДУ &НачДата И &КонДата
	|	И КурсыВалют.Валюта В (&Валюта)
	|СГРУППИРОВАТЬ ПО
	|	КурсыВалют.Период,
	|	КурсыВалют.Валюта,
	|	КурсыВалют.Курс,
	|	КурсыВалют.Кратность
	|УПОРЯДОЧИТЬ ПО
	|	Период,
	|	Валюта	
	|";
	
	
	СписокВалют = Новый СписокЗначений;
	
	спПоказателейГрафика = Новый Массив(4);
	Точка = Новый Массив(4);

	Для сч=1 по 4 цикл
		спПоказателейГрафика[сч-1] = ПолучитьТекушийСостав(сч);
		
		ТекГраф = ЭтаФорма["График"+сч];
		ТекГраф.Очистить();
		Заг = "";
		Для каждого Строка из спПоказателейГрафика[сч-1] цикл
			ТекГраф.Серии.Добавить(Строка.Значение.Наименование);
			Заг = Заг +?(СокрЛП(Заг)="","","/")+Справочники.Валюты.НайтиПоНаименованию(Строка.Значение.Наименование).НаименованиеПолное;
			СписокВалют.Добавить(Строка.Значение);	
		КонецЦикла;
		ТекГраф.ОбластьЗаголовка.Текст = Заг;
	КонецЦикла;
	
	Дней = Константы.ПоказыватьКурсЗаПоследние.Получить();
	Если Дней = 0 тогда
		Дней = 30;
	Конецесли;	
	КонецПериода = СервисныеФункции.ПолучитьДатуСервера();
	Запрос.УстановитьПараметр("Валюта",СписокВалют);
	Запрос.УстановитьПараметр("НачДата",НачалоДня(КонецПериода)-Дней*24*60*60);
	Запрос.УстановитьПараметр("КонДата",КонецДня(КонецПериода));
	
	Результат = Запрос.Выполнить();
	Если Не Результат.Пустой() тогда
		Выборка	= Результат.Выбрать();
		Пока Выборка.Следующий() Цикл
			Для сч=1 по 4 цикл
				ТекГраф = ЭтаФорма["График"+сч];
				Индекс=0;
				Для каждого Строка из спПоказателейГрафика[сч-1] цикл
					Если Выборка.Валюта = Строка.Значение тогда
						Точка[сч-1] = ТекГраф.УстановитьТочку(Формат(Выборка.Период,"ДЛФ=Д"));
						ТекГраф.УстановитьЗначение(Точка[сч-1],ТекГраф.Серии[Индекс],Выборка.Курс);
					КонецЕсли;	
					Индекс=Индекс+1;
				КонецЦикла;
			КонецЦикла;
			
		КонецЦикла;	
	КонецЕсли;
	
КонецПроцедуры	

&НаСервереБезКонтекста
Функция ПроверитьАктуальныйКурс()
	
	Запрос = Новый Запрос;
	Запрос.Текст = "
	|ВЫБРАТЬ
	|МАКСИМУМ(КурсыВалютСрезПоследних.Период) КАК Период
	|ИЗ
	|РегистрСведений.КурсыВалют.СрезПоследних КАК КурсыВалютСрезПоследних
	|";
	
	Рез = Запрос.Выполнить();
	Если Не Рез.Пустой() тогда 
		Выборка = Рез.Выбрать();
		Выборка.Следующий();
		ПоследняяДата = Выборка.Период;
	Иначе
		ПоследняяДата = '00010101000000';
	КонецЕсли;
	
	Если НачалоДня(ПоследняяДата) < НачалоДня(ТекущаяДата()) тогда
		Возврат ПоследняяДата;
	КонецЕсли;	
	Возврат 1;
	
КонецФункции

&НаКлиенте
Процедура ПриОткрытии(Отказ)
		
	Рез = ПроверитьАктуальныйКурс();
	Если Рез <> 1 тогда
		СтруктураОтбора = Новый Структура() ;
		СтруктураОтбора.Вставить("НачДата",рез);
		СтруктураОтбора.Вставить("КонДата",СервисныеФункции.ПолучитьДатуСервера());
		Парам = Новый Структура("Отбор", СтруктураОтбора);
		ОткрытьФорму("Обработка.ПолучениеКурсаВалют.Форма",Парам);
	КонецЕсли;
	
	ПостроениеГрафика();
	
КонецПроцедуры

/////////Обработчики контекстного меню графиков формы
/////////Добавление////////////////////////////
&НаКлиенте
Процедура Добавить(Команда)
   //привязана к команде Добавить
   Перем ВыбЗнач;

    Парам = Новый Структура("График",ЭтаФорма.ТекущийЭлемент.Имя);
	
    Массив = Новый Массив;
    Массив.Добавить(Тип("СправочникСсылка.Валюты"));

    ОписаниеТипов = Новый ОписаниеТипов(Массив);

    Оповещение =     Новый ОписаниеОповещения("ПослеВыбораЭлементаДобавить", ЭтаФорма, Парам);
    ПоказатьВводЗначения(Оповещение,   ВыбЗнач, "Введите значение", ОписаниеТипов);
	
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ДобавитьНаСервере(Валюта, Парам)
	
    ТекГраф = Число(Прав(Парам.График,1));
	
    Запись = РегистрыСведений.ГрафикиОсновнойФормы.СоздатьМенеджерЗаписи();
    Запись.Валюта = Валюта;
    Запись.График = ТекГраф;
    Запись.Записать();
		
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораЭлементаДобавить(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
    Если ВыбранныйЭлемент<>Неопределено Тогда
	ДобавитьНаСервере(ВыбранныйЭлемент, ДополнительныеПараметры);
	ПостроениеГрафика();
    КонецЕсли;
КонецПроцедуры

////////Удаление////////////////////
&НаКлиенте
Процедура Удалить(Команда)
    //привязана к команде Удалить
    Парам = Новый Структура("График",ЭтаФорма.ТекущийЭлемент.Имя);
    Рез = ПолучитьТекушийСостав(ЭтаФорма.ТекущийЭлемент.Имя);
    Если НЕ Рез.Количество()=0  тогда
	Оповещение = Новый ОписаниеОповещения("ПослеВыбораЭлементаУдалить", ЭтаФорма,Парам);
	Рез.ПоказатьВыборЭлемента(Оповещение, "Выберите показатель");
    Конецесли;	
КонецПроцедуры

&НаСервереБезКонтекста
Процедура УдалитьНаСервере(Валюта, Парам)
	
    ТекГраф = Число(Прав(Парам.График,1));
	
    Набор = РегистрыСведений.ГрафикиОсновнойФормы.СоздатьНаборЗаписей();
    Набор.Отбор.Валюта.Установить(Валюта);
    Набор.Отбор.График.Установить(ТекГраф);
    Набор.Записать();
		
КонецПроцедуры

&НаКлиенте
Процедура ПослеВыбораЭлементаУдалить(ВыбранныйЭлемент, ДополнительныеПараметры) Экспорт
    Если ВыбранныйЭлемент<>Неопределено Тогда
	УдалитьНаСервере(ВыбранныйЭлемент.Значение, ДополнительныеПараметры);
	ПостроениеГрафика();
    КонецЕсли;
КонецПроцедуры

////////////////Очистка////////////////////////
&НаСервереБезКонтекста
Процедура ОчиститьНаСервере(Парам)
	
    ТекГраф = Число(Прав(Парам.График,1));
	
    Набор = РегистрыСведений.ГрафикиОсновнойФормы.СоздатьНаборЗаписей();
    Набор.Отбор.График.Установить(ТекГраф);
    Набор.Записать();
		
КонецПроцедуры

&НаКлиенте
Процедура Очистить(Команда)
    //привязана к команде Очистить
    Парам = Новый Структура("График",ЭтаФорма.ТекущийЭлемент.Имя);
    ОчиститьНаСервере(Парам);
    ПостроениеГрафика();
КонецПроцедуры

В результате получилась форма с настраиваемыми графиками. На каждый можно добавить любое произвольное количество валют или металлов. Информация о том, какая валюта принадлежит какому графику хранится в непериодическом, независимом регистре сведений ГрафикиОсновнойФормы.

Диаграммы 1С8.3

Диаграммы 1С8.3

Комментариев нет »

No comments yet.

RSS feed for comments on this post. TrackBack URL

Leave a comment

Для отправки комментария вам необходимо авторизоваться.