Имя: Пароль:
1C
1С v8
Вопросы от стажера по книге Радченко
,
0 intern-1c
 
04.05.13
23:11
Здравствуйте, уважаемые специалисты!

Учусь, читаю Радченко. Периодически возникают разные вопросы. Если никто не возражает, буду писать их сюда. Буду благодарен, если кто-то будет на них отвечать.

Вопрос 1:
9 занятие. Периодические регистры сведений.

Завел периодический регистр сведений "Цены" с периодом в пределах секунды.

Затем для документа ОказаниеУслуг в модуле формы документа был добавлен обработчик события, который при выборе Номенклатуры в очередной строке ТЧ подставляет для данной Номенклатуры цену из вновь созданного регистра.

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

Далее такая ситуация. В регистре сведений для Номенклатуры "Ремонт импортного телевизора" есть единственная запись на дату Дата = 04.05.2013 20:47:59 с Ценой = 800.

Когда я создаю новый документ "ОказаниеУслуг", то по умолчанию дата документа равна 04.05.2013 00:00:00 и при заполнении ТЧ в поле Цена подставляется 0. Но если перед редактированием ТЧ вручную очистить поле Дата и ничего там не писать, то цена подставляется. Причем, я проверяю отладчиком: в случае пустого поля Дата в функцию передается значение 01.01.0001 00:00:00.

Вопросы:

1. Почему при создании нового документа подставляется не текущая секунда, а дата на начало суток?

2. Почему в моем случае метод регистра сведений ПолучитьПоследнее вернул корректно сформированную структуру со значением Цена=0, если на указанную дату не было никаких записей? В синтакс помощнике ничего не сказано про случай, когда по указанным значениям измерений в Отбор ничего не попадает.

3. А что делать, если цена реально может быть установлена в 0, но надо знать, правда ли ее установили равной 0, или ее вообще не устанавливали?

4. Почему для даты 04.05.2013 00:00:00 возвращается Цена = 0, а для даты 01.01.0001 00:00:00 возвращается Цена = 800, хотя обе эти даты находятся ранее, чем дата, когда для данной номенклатуры была единственный раз установлена цена?
1 intern-1c
 
04.05.13
23:16
На всякий случай, выкладываю dt-ку.
http://zalil.ru/34484159
2 EugeniaK
 
04.05.13
23:25
(0) 1. Нет смысла ставить текущую секунду, так как дата все равно изменится при перепроведении.
Ставится дата на момент проведения. При создании документа дата проведения неизвестна, поэтому по умолчанию ставится начало дня.
Да и вообще стандартом считается регистр "Цены" по дням, а не по секундам. Не нужны никому реально цены по секундам.
2. Так работает метод.
3. Используй метод "СрезПоследних". Он вернет таблицу.
4. Дата 01.01.0001 00:00:00  это в терминах 1С "Пустая дата". Т.е. считается, что ты не задал дату вообще. В этом случае метод возвращает последнее значение без привязки к дате документа.
3 Alexman13
 
04.05.13
23:26
(0) Вот здесь http://devtrainingforum.v8.1c.ru/forum/ на твои вопросы может ответить сам Радченко
4 vladimir-boy
 
04.05.13
23:28
(0) Честно говоря я б сам бы проэксперементировал, на начальном этапе понял как работает, а потом двинулся бы дальшею Если будешь всё изучать досконально и захочешь познать все нюансы взаимодействия с платформой, то будет обучение ООООООООООЧЕЕЕЕЕЕЕЕЕНЬ ДОЛГИМ.
5 intern-1c
 
04.05.13
23:49
(2) Евгения, спасибо!
Я сделал вывод, что чтобы данный механизм корректно отрабатывал (РЗ Цены оставляем в пределах секунды) надо:
1. Поставить в форме обработку события ПриОткрытии и вручную указать Объект.Дата = ТекущаяДата.
2. Вместо метода ПолучитьПоследнее использовать СрезПоследних.

Выглядит это так:
Функция РозничнаяЦена(АктуальнаяДата, ЭлементНоменклатуры) Экспорт

   //Создать вспомогательный объект Отбор
   Отбор = Новый Структура("Номенклатура", ЭлементНоменклатуры);
   
   //Получить актуальные значения ресурсов регистра
   ЗначениеРесурсов = РегистрыСведений.Цены.СрезПоследних(АктуальнаяДата, Отбор);
   Возврат ЗначениеРесурсов.Цена;

КонецФункции // РозничнаяЦена()

К сожалению, возникли новые вопросы:
1.5. В моем случае теперь дата подставляется на текущую секунду не только при создании нового документа, но и при повторном открытии. Неясно, как сделать, чтобы в созданных ранее документах дата не менялась. Поле "Проведено" не подходит. Может быть, какие-то другие поля объекта позволяют понять, записывался ли он ранее?
1.6. СрезПоследних вернул мне какую-то странную таблицу, в которой куча информации о структуре самой таблицы и формате ее колонок, но нет ни одной записи. При том, что 1 запись должна была быть.
6 EugeniaK
 
05.05.13
00:21
(5)
1.5 У документа есть метод ЭтоНовый(). Им можно проверить, новый закумент или нет.
1.6 Таблица нормальная. Не так смотришь на таблицу. Ты в отладчике видишь структуру тавлицы. Правый клик мыши и "Показать значения"
ЗначениеРесурсов = РегистрыСведений.Цены.СрезПоследних(АктуальнаяДата, Отбор);
Если ЗначениеРесурсов.Следующий() Тогда
   Возврат ЗначениеРесурсов.Цена;
Иначе
   Возврат 0;
КонецЕсли;
7 EugeniaK
 
05.05.13
00:26
(6) Вернее
Если ЗначениеРесурсов.Количество() > 0 Тогда
   Возврат ЗначениеРесурсов[0].Цена;
Иначе
   Возврат 0;
КонецЕсли;
8 Злопчинский
 
05.05.13
00:31
(2) > Да и вообще стандартом считается регистр "Цены" по дням, а не по секундам.
- ну-ну.. я посмотрю как ты сторгуешь когда цена с утра была 45 руб, а в обед скакнула процентов на 50...
9 intern-1c
 
05.05.13
00:43
(6) Спасибо огромное!
А как правильно воспользоваться методом ЭтоНовый() из модуля формы?

Пробую так:
Если Объект.ЭтоНовый() Тогда
- не работает, метод не определен. Вижу в синтакс-помощнике, что метод серверный. Делаю так:
Если РаботаСДокументами.ПроверкаЧтоДокументНовый(Объект) Тогда
И в самом общем модуле так:
Возврат Документ.ЭтоНовый();
Все равно ругается, что неизвестный метод. Если в общий модуль передаю не Объект, а Объект.Ссылка - эффект тот же.
10 intern-1c
 
05.05.13
00:44
Может быть, в общем модуле надо создать новый объект типа Документы.ОказаниеУслуг, вписать в него ссылку и с ним попробовать?
11 unkairosed
 
05.05.13
00:45
(8) В каких случаях прейскурант цен на одну и ту же продукцию может устанавливаться дважды на день?
12 unkairosed
 
05.05.13
00:46
(9) Объект.Ссылка.Пустая()
13 Конфигуратор1с
 
05.05.13
00:49
(9) Тебя Женечка ввела в заблуждение - Это новый работает в толстом клиенте.
14 Конфигуратор1с
 
05.05.13
00:55
(13) Хотя если напишешь так на сервере
Если РеквизитФормыВЗначение("объект").ЭтоНовый() Тогда
то будет работать
15 Конфигуратор1с
 
05.05.13
00:56
(14) но (12) лучше
16 EugeniaK
 
05.05.13
01:10
(8) В этом случае я поставлю новую цену с начала дня, а не с 11.35
(9) ЭтоНовый() это метод объекта.
В модуле формы объекта как такового нет.
Есть его отображение в переменной "Объект"
Соответственно в модуле формы действительно можно обратиться только преобразовав отображение объекта в реальный объект функцией РеквизитФормыВЗначение("объект")
Но вариант (12) лучше.
17 intern-1c
 
05.05.13
01:15
Уфф... Отработала.

Результат получился такой:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
   Если ПроверкаЧтоДокументНовый() Тогда
       Объект.Дата = ТекущаяДата();
   КонецЕсли;
КонецПроцедуры

&НаСервере
Функция ПроверкаЧтоДокументНовый()
   ДокОказаниеУслуг = РеквизитФормыВЗначение("Объект");
   Возврат ДокОказаниеУслуг.ЭтоНовый();
КонецФункции

Или так:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
   Если Объект.Ссылка.Пустая() Тогда
       Объект.Дата = ТекущаяДата();
   КонецЕсли;
КонецПроцедуры

Евгения, Конфигуратор1с, nkairosed, спасибо!
18 Конфигуратор1с
 
05.05.13
01:22
(17) &НаКлиенте
Процедура ПриОткрытии(Отказ)
   Если ПроверкаЧтоДокументНовый() Тогда
       Объект.Дата = ТекущаяДата();
   КонецЕсли;
КонецПроцедуры

&НаСервере
Функция ПроверкаЧтоДокументНовый()
   ДокОказаниеУслуг = РеквизитФормыВЗначение("Объект");
   Возврат ДокОказаниеУслуг.ЭтоНовый();
КонецФункции - это неправильно. Так как ты с клиента вызываешь сервер. Надо юзать процедуру присозданиинасервере
19 Конфигуратор1с
 
05.05.13
01:23
(18) &НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
   Если РеквизитФормыВЗначение("объект").ЭтоНовый() Тогда
        Объект.Дата = ТекущаяДата();
   КонецЕсли;    
КонецПроцедуры
20 intern-1c
 
05.05.13
01:27
Ясно. Я просто думал, что ПриСозданииНаСервере по определению не отработает, если документ был создан раньше и теперь повторно открывается. Теперь понял, что речь идет именно о создании формы, которая создается каждый раз заново.
Спасибо
21 Конфигуратор1с
 
05.05.13
01:29
(20) смотри. Форма в принципе создается на сервере и передается клиенту. Поэтому если надо заполнить форму делай это на сервере. Чем меньше серверных вызовов тем лучше.
22 intern-1c
 
05.05.13
01:32
На самом деле, неочевидная истина. Буду знать. Еще раз спасибо )
23 GROOVY
 
05.05.13
09:08
Проверку новый или нет можно делать без конфертации данных формы в прикладное значение "Объект.Ссылка.Пустая()"
24 zak555
 
05.05.13
09:48
(24)

ЭтоНовый = НЕ ЗначениеЗаполнено(Параметры.Ключ);




?
25 zak555
 
05.05.13
09:51
*или

ЭтоНеНовый = ЗначениеЗаполнено(Параметры.Ключ);