Имя: Пароль:
1C
1С v8
О правильном коде
0 Chuvaschow
 
03.08.15
13:55
Здравствуйте!

Есть код в модуле формы.

&НаКлиенте
Процедура ПолевыеРаботыВидРаботыПриИзменении(Элемент)
    Строка = Элементы.ПолевыеРаботы.ТекущиеДанные;
    Строка.ПлановыйРасход = Строка.Выработано * ПолучитьНормуРасхода(Строка.ВидРаботы);
    Объект.ПлановыйРасход = Объект.ПолевыеРаботы.Итог("ПлановыйРасход");
    
    РасчетнаяЧасть(Элемент);
КонецПроцедуры

&НаКлиенте
Процедура РасчетнаяЧасть(Элемент)
    Строка = Элементы.ПолевыеРаботы.ТекущиеДанные;
    
    КоэффициентУГ = ПолучитьКоэффициентУГ(Объект.Трактор);
    НормаВыработки = ПолучитьНормуВыработки(Строка.ВидРаботы);
    Расценка = ПолучитьРасценку(Строка.ВидРаботы);
    //ПочасоваяРасценка = ПредопределенноеЗначение("Константы.ПочасоваяРасценка");
    
    Строка.УсловныеГектарыПерегон = Строка.Перегон / 7 * КоэффициентУГ;
    
    Если КоэффициентУГ = 0 Или НормаВыработки = 0 Тогда
            Строка.УсловныеГектарыРабота = 0;
        Иначе
            Строка.УсловныеГектарыРабота = Строка.Выработано / НормаВыработки * КоэффициентУГ;
    КонецЕсли;
        
    Объект.УсловныеГектары = Объект.ПолевыеРаботы.Итог("УсловныеГектарыПерегон") + Объект.ПолевыеРаботы.Итог("УсловныеГектарыРабота");
    
    // Считаем зарплату за работу
    Если ПолучитьЕдИзм(Строка.ВидРаботы) = ПредопределенноеЗначение("Перечисление.ЕдиницыИзмерения.га") Или
        ПолучитьЕдИзм(Строка.ВидРаботы) = ПредопределенноеЗначение("Перечисление.ЕдиницыИзмерения.тн")Тогда
        Строка.ЗарплатаРабота = Расценка * Строка.Выработано;
    Иначе
        Строка.ЗарплатаРабота = (Расценка * Объект.ЧасовРаботе) + (Расценка * 0.2 * Объект.ЧасовНочных);
    КонецЕсли;

    // Считаем зарплату за перегон
    //Строка.ЗарплатаПерегон = Строка.Перегон * ПочасоваяРасценка;

    
    
    // Считаем Тонно-километры
    //Объект.ТонноКилометры = Объект.КоличествоТн * Объект.ВидРаботы.Пробег;
    
    ПодсчетИтогов();
    
КонецПроцедуры


Процедура ПодсчетИтогов()
    // Итоги по зарплате
    Объект.ЗарплатаПерегон = Объект.ПолевыеРаботы.Итог("ЗарплатаПерегон");
    Объект.ЗарплатаРабота = Объект.ПолевыеРаботы.Итог("ЗарплатаРабота");
    Объект.ЗарплатаИтого = Объект.ЗарплатаПерегон + Объект.ЗарплатаРабота;
КонецПроцедуры

&НаКлиенте
Процедура ОстатокГСМВыездПриИзменении(Элемент)
    ОстатокГСМВыездПриИзмененииНаСервере();
КонецПроцедуры

&НаСервере
Процедура ОстатокГСМВыездПриИзмененииНаСервере()
    Объект.ФактическийРасход = Объект.ОстатокГСМВыезд + Объект.Выдано - Объект.ОстатокГСМВозвращение;
    
    Если Объект.ФактическийРасход < 0 Тогда
        Сообщить("В баке не может быть отрицательное топливо!");
    КонецЕсли

КонецПроцедуры  

Функция ПолучитьКоэффициентУГ(Ссылка)
    Возврат Ссылка.КоэффициентУГ;
КонецФункции

Функция ПолучитьНормуВыработки(Ссылка)
    Возврат Ссылка.НормаВыработки;
КонецФункции

Функция ПолучитьНормуРасхода(Ссылка)
    Возврат Ссылка.НормаРасхода;
КонецФункции

Функция ПолучитьРасценку(Ссылка)
    Возврат Ссылка.Расценка;
КонецФункции

Функция ПолучитьЕдИзм(Ссылка)
    Возврат Ссылка.ЕдИзм;
КонецФункции

Функция ПолучитьПробег(Ссылка)
    Возврат Ссылка.Пробег;
КонецФункции

Функция ПолучитьКонстантуПочасоваяРасценка()
    Возврат Константы.ПочасоваяРасценка
КонецФункции


В процедуре РасчетнаяЧасть не получается дотянуться до реквизитов справочника. Поэтому приходится писать функции на возврат значений этих реквизитов. Скажите, насколько это не вежливо ? :) Как правильно?

Здесь же невозможность дотянуться до Перечислений, отсюда такое ПредопределенноеЗначение. Если перевести всю процедуру НаСервере, тогда, что-то другое не считается (не помню уже).

Как нужно писать такие вещи?
P.S. этот код работает :)
1 Fragster
 
гуру
03.08.15
13:59
Функция ПолучитьДанныеСсылки(СписокПолей, Ссылка)
  Струкутра = Новый СТруктура(СписокПолей);
  ЗаоплнитьЗначенияСвойств(Структура, Ссылка);
КонецФункции

Еще в БСП есть несколько функций, которые то же через запрос делают, но они почему-то галки "вызов сервера" у модуля сняли, и объяснили это "безопасностью".
2 Fragster
 
гуру
03.08.15
14:00
ну, там еще возврат надо написать
3 Fragster
 
гуру
03.08.15
14:01
почему подсчет итогов выполняется на сервере?
4 Chuvaschow
 
03.08.15
14:04
Потому что будет еще две табличные части, у каждой свои процедуры расчета. а почему на сервере? опечатка видимо скопировал из черновика так
5 rabbidX
 
03.08.15
14:08
Что именно мешает вынести расчетную часть на сервер? В Вашем варианте слишком много вызовов сервера.
6 Chuvaschow
 
03.08.15
14:12
Но я правильно понимаю, что из табличной части до реквизита справочника так просто не дотянуться? Только через возврат?
7 Asmody
 
03.08.15
14:12
Как только вы представите, что ваш сервер стоит в дата-центре в какой-нибудь Калифорнии, а клиент запущен на МКС, вы сразу поймёте как писать клиент-серверное взаимодействие.
8 Armando
 
03.08.15
14:14
(7) Зачем представлять? Есть же имитация задержек
9 Kvant1C
 
03.08.15
14:15
+(7) причем клиент - мобильный и канал не 3g
10 Stepa86
 
03.08.15
14:16
(1) Для решений, которые продаются огромным тиражом, есть смысл иногда думать над безопасностью. Вот тут подробнее расписано про причины снятия галки http://its.1c.ru/db/v8std#content:-2145782969:hdoc

(0) Каждое обращение к реквизиту - это все равно вызов сервера. Таблица справочника все равно не на клиенте хранится. Лучше б один раз получил все нужные реквизиты за одно обращение, а уже потом их использовал
11 GROOVY
 
03.08.15
14:16
Жесть какая.

Чего бы раз уж не умеем кодить УФ, расчетную часть на сервер не положить?
12 Chuvaschow
 
03.08.15
14:17
Понял. Что еще не красиво?
13 Asmody
 
03.08.15
14:18
(8) Если бы имитация задержек снимала деньги за связь, было бы эффективнее.
14 Fragster
 
гуру
03.08.15
14:25
(10) оно понятно, что через функцию "ПолучитьЗначениеРеквизитовОбъекта" таким образом можно получить все данные, у которых есть право "Чтение" у пользователя. Но если у него не должно быть доступа к данным, не правильнее ли закрыть это правами?
Лично я скопипастил эти функции в общий модуль с галкой "вызов сервера", как раз чтобы не писать кучи кода в каждой форме.
15 gigi789
 
03.08.15
14:26
КоэффициентУГ порадовал
16 Fragster
 
гуру
03.08.15
14:28
по хорошему - надо хранить ставку в документе. и коэффициенты и значения констант - также. Вообще, всё, что участвует в расчете, нужно хранить в документе.

Реализовать экспортные функции перезаполнения этих данных. А то при перепроведении документа _внезапно_ могут "поплыть остатки".
17 Fragster
 
гуру
03.08.15
14:29
док коэффициентом - я имею ввиду магическое число 0.2, например
18 Fragster
 
гуру
03.08.15
14:29
*под коэффициентом
19 Fragster
 
гуру
03.08.15
14:29
и 7 тоже
20 Stepa86
 
03.08.15
14:32
(14) Реквизит может быть нужен для логики программы и галка "Просмотр" в роли снята, но через вызов сервера можно получить к нему доступ на просмотр. Видел более веселый метод ПолучитьЗначениеРеквизитаПодПолнымиПравами(

Я предпочитаю на клиенте не дергать данные с сервера через модули "ВызовСервера", а делать все за один вызов и в серверном модуле. Но от ВызовСервера не уйти, т.к. разрабатываю под УПП. В обычном режиме это необходимая вещь.
21 Fragster
 
гуру
03.08.15
14:34
ты лучше расскажи, как избавляешь от дублирования кода при выставлении доступности видимости из ПриСозданииНаСервере и при изменении реквизитов на клиенте, например? Ведь в форме нет &НаКлиентеНаСервере?
22 gigi789
 
03.08.15
14:35
Процедура ОстатокГСМВыездПриИзмененииНаСервере()
Зачем на сервере??
23 gigi789
 
03.08.15
14:36
Процедура ПодсчетИтогов()Зачем насервере
24 gigi789
 
03.08.15
14:37
Процедура ПолевыеРаботыВидРаботыПриИзменении(Элемент)
    Строка = Элементы.ПолевыеРаботы.ТекущиеДанные;
Процедура РасчетнаяЧасть(Элемент)
    Строка = Элементы.ПолевыеРаботы.ТекущиеДанные;
Если делаем много раз одно и тоже хорошо
25 Stepa86
 
03.08.15
14:38
(21) &НаКлиентеНаСервереБезКонтекста
26 Fragster
 
гуру
03.08.15
14:38
(25) и туда передаешь элементы формы?
27 Stepa86
 
03.08.15
14:39
(21) +(25)
&НаКлиентеНаСервереБезКонтекста
Процедура СделатьЧтотоИТамИТам(Форма)

КонецПроцедуры


но для установки видимости/доступности можно просто вызывать серверную процедуру, изменение свойств элементов один фик приводит к вызову сервера. Хотя в 8.3.7 обещают это исправить
28 Fragster
 
гуру
03.08.15
14:41
(27) доступность сервер не дергает... отсюда получается, что происходит даже тройной вызов:

&НаКлиенте
Процедура ЭтоЗапросПриИзменении(Элемент)
    ОбновитьДоступность();
КонецПроцедуры

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

&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    ОбновитьДоступность();
КонецПроцедуры
29 Stepa86
 
03.08.15
14:42
(28) у тебя доступ на ИТС есть?

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

Для того чтобы избежать дублирования кода, такие процедуры и функции необходимо размещать в модуле формы с директивой компиляции &НаКлиентеНаСервереБезКонтекста и передавать в них контекст самостоятельно в виде параметра. В качестве контекста может выступать либо сама форма (УправляемаяФорма), либо ее реквизит (ДанныеФормыСтруктура)."

http://its.1c.ru/db/v8std#content:-2145783017:hdoc
30 Stepa86
 
03.08.15
14:46
+(29) я как раз недавно начал перечитывать систему стандартов и методик и открыл для себя много нового, а вот реализацию (21) неоднократно наблюдал в УП и УТ11
31 Fragster
 
гуру
03.08.15
15:25
(29) не является ли это костылем от отсутствия в платформе &НаКлиентеНаСервере?
32 Stepa86
 
03.08.15
15:32
(31) У меня язык не поворачивается назвать рекомендацию вендора - костылем. Если б было лучше решение, тогда да. Посмотрим чо будет в 8.3.7. Возможно управлять видимостью и доступностью придется только на клиенте
33 Chuvaschow
 
03.08.15
15:37
Всем спасибо. Все понял. Исправлюсь
34 Fragster
 
гуру
03.08.15
16:34
(32) судя по http://v8.1c.ru/o7/201505layout/index.htm так и будет